From 50df4d8b0f6e1971b930f3158c9ee0e4263e636d Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 31 Dec 2008 03:01:23 +0800 Subject: ACPICA: Restructure includes into public/private acpi.h now includes only the "public" acpica headers. All other acpica headers are "private" and should not be included by acpica users. One new file, accommon.h is used to include the commonly used private headers for acpica code generation. Future plans are to move all private headers to a new subdirectory. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/namespace/nsnames.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi/namespace/nsnames.c') diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index 42a39a7c96e9..b7e301848ba7 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -42,6 +42,7 @@ */ #include +#include #include #include -- cgit v1.2.3-59-g8ed1b From 95b482a8d31116f3f5c2a5089569393234d06385 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 9 Jan 2009 00:13:17 -0500 Subject: ACPICA: create acpica/ directory also, delete sleep/ and delete ACPI_CFLAGS from Makefile Signed-off-by: Len Brown --- drivers/acpi/Makefile | 22 +- drivers/acpi/acpica/Makefile | 44 ++ drivers/acpi/acpica/dsfield.c | 650 ++++++++++++++++ drivers/acpi/acpica/dsinit.c | 205 +++++ drivers/acpi/acpica/dsmethod.c | 629 +++++++++++++++ drivers/acpi/acpica/dsmthdat.c | 718 ++++++++++++++++++ drivers/acpi/acpica/dsobject.c | 813 ++++++++++++++++++++ drivers/acpi/acpica/dsopcode.c | 1469 ++++++++++++++++++++++++++++++++++++ drivers/acpi/acpica/dsutils.c | 869 +++++++++++++++++++++ drivers/acpi/acpica/dswexec.c | 746 ++++++++++++++++++ drivers/acpi/acpica/dswload.c | 1203 +++++++++++++++++++++++++++++ drivers/acpi/acpica/dswscope.c | 214 ++++++ drivers/acpi/acpica/dswstate.c | 753 ++++++++++++++++++ drivers/acpi/acpica/evevent.c | 313 ++++++++ drivers/acpi/acpica/evgpe.c | 722 ++++++++++++++++++ drivers/acpi/acpica/evgpeblk.c | 1227 ++++++++++++++++++++++++++++++ drivers/acpi/acpica/evmisc.c | 621 +++++++++++++++ drivers/acpi/acpica/evregion.c | 1070 ++++++++++++++++++++++++++ drivers/acpi/acpica/evrgnini.c | 684 +++++++++++++++++ drivers/acpi/acpica/evsci.c | 183 +++++ drivers/acpi/acpica/evxface.c | 821 ++++++++++++++++++++ drivers/acpi/acpica/evxfevnt.c | 871 +++++++++++++++++++++ drivers/acpi/acpica/evxfregn.c | 254 +++++++ drivers/acpi/acpica/exconfig.c | 536 +++++++++++++ drivers/acpi/acpica/exconvrt.c | 692 +++++++++++++++++ drivers/acpi/acpica/excreate.c | 522 +++++++++++++ drivers/acpi/acpica/exdump.c | 1060 ++++++++++++++++++++++++++ drivers/acpi/acpica/exfield.c | 340 +++++++++ drivers/acpi/acpica/exfldio.c | 961 +++++++++++++++++++++++ drivers/acpi/acpica/exmisc.c | 726 ++++++++++++++++++ drivers/acpi/acpica/exmutex.c | 474 ++++++++++++ drivers/acpi/acpica/exnames.c | 436 +++++++++++ drivers/acpi/acpica/exoparg1.c | 1050 ++++++++++++++++++++++++++ drivers/acpi/acpica/exoparg2.c | 605 +++++++++++++++ drivers/acpi/acpica/exoparg3.c | 273 +++++++ drivers/acpi/acpica/exoparg6.c | 341 +++++++++ drivers/acpi/acpica/exprep.c | 590 +++++++++++++++ drivers/acpi/acpica/exregion.c | 499 ++++++++++++ drivers/acpi/acpica/exresnte.c | 278 +++++++ drivers/acpi/acpica/exresolv.c | 551 ++++++++++++++ drivers/acpi/acpica/exresop.c | 701 +++++++++++++++++ drivers/acpi/acpica/exstore.c | 716 ++++++++++++++++++ drivers/acpi/acpica/exstoren.c | 304 ++++++++ drivers/acpi/acpica/exstorob.c | 209 +++++ drivers/acpi/acpica/exsystem.c | 303 ++++++++ drivers/acpi/acpica/exutils.c | 421 +++++++++++ drivers/acpi/acpica/hwacpi.c | 185 +++++ drivers/acpi/acpica/hwgpe.c | 469 ++++++++++++ drivers/acpi/acpica/hwregs.c | 353 +++++++++ drivers/acpi/acpica/hwsleep.c | 629 +++++++++++++++ drivers/acpi/acpica/hwtimer.c | 188 +++++ drivers/acpi/acpica/hwxface.c | 593 +++++++++++++++ drivers/acpi/acpica/nsaccess.c | 676 +++++++++++++++++ drivers/acpi/acpica/nsalloc.c | 497 ++++++++++++ drivers/acpi/acpica/nsdump.c | 709 +++++++++++++++++ drivers/acpi/acpica/nsdumpdv.c | 141 ++++ drivers/acpi/acpica/nseval.c | 278 +++++++ drivers/acpi/acpica/nsinit.c | 593 +++++++++++++++ drivers/acpi/acpica/nsload.c | 315 ++++++++ drivers/acpi/acpica/nsnames.c | 265 +++++++ drivers/acpi/acpica/nsobject.c | 441 +++++++++++ drivers/acpi/acpica/nsparse.c | 204 +++++ drivers/acpi/acpica/nspredef.c | 1065 ++++++++++++++++++++++++++ drivers/acpi/acpica/nssearch.c | 415 ++++++++++ drivers/acpi/acpica/nsutils.c | 997 ++++++++++++++++++++++++ drivers/acpi/acpica/nswalk.c | 296 ++++++++ drivers/acpi/acpica/nsxfeval.c | 812 ++++++++++++++++++++ drivers/acpi/acpica/nsxfname.c | 360 +++++++++ drivers/acpi/acpica/nsxfobj.c | 287 +++++++ drivers/acpi/acpica/psargs.c | 752 ++++++++++++++++++ drivers/acpi/acpica/psloop.c | 1088 ++++++++++++++++++++++++++ drivers/acpi/acpica/psopcode.c | 810 ++++++++++++++++++++ drivers/acpi/acpica/psparse.c | 701 +++++++++++++++++ drivers/acpi/acpica/psscope.c | 265 +++++++ drivers/acpi/acpica/pstree.c | 312 ++++++++ drivers/acpi/acpica/psutils.c | 244 ++++++ drivers/acpi/acpica/pswalk.c | 110 +++ drivers/acpi/acpica/psxface.c | 385 ++++++++++ drivers/acpi/acpica/rsaddr.c | 381 ++++++++++ drivers/acpi/acpica/rscalc.c | 618 +++++++++++++++ drivers/acpi/acpica/rscreate.c | 468 ++++++++++++ drivers/acpi/acpica/rsdump.c | 771 +++++++++++++++++++ drivers/acpi/acpica/rsinfo.c | 206 +++++ drivers/acpi/acpica/rsio.c | 290 +++++++ drivers/acpi/acpica/rsirq.c | 266 +++++++ drivers/acpi/acpica/rslist.c | 203 +++++ drivers/acpi/acpica/rsmemory.c | 236 ++++++ drivers/acpi/acpica/rsmisc.c | 561 ++++++++++++++ drivers/acpi/acpica/rsutils.c | 727 ++++++++++++++++++ drivers/acpi/acpica/rsxface.c | 571 ++++++++++++++ drivers/acpi/acpica/tbfadt.c | 610 +++++++++++++++ drivers/acpi/acpica/tbfind.c | 140 ++++ drivers/acpi/acpica/tbinstal.c | 574 ++++++++++++++ drivers/acpi/acpica/tbutils.c | 582 ++++++++++++++ drivers/acpi/acpica/tbxface.c | 735 ++++++++++++++++++ drivers/acpi/acpica/tbxfroot.c | 274 +++++++ drivers/acpi/acpica/utalloc.c | 383 ++++++++++ drivers/acpi/acpica/utcopy.c | 970 ++++++++++++++++++++++++ drivers/acpi/acpica/utdebug.c | 651 ++++++++++++++++ drivers/acpi/acpica/utdelete.c | 677 +++++++++++++++++ drivers/acpi/acpica/uteval.c | 752 ++++++++++++++++++ drivers/acpi/acpica/utglobal.c | 823 ++++++++++++++++++++ drivers/acpi/acpica/utinit.c | 152 ++++ drivers/acpi/acpica/utmath.c | 312 ++++++++ drivers/acpi/acpica/utmisc.c | 1093 +++++++++++++++++++++++++++ drivers/acpi/acpica/utmutex.c | 342 +++++++++ drivers/acpi/acpica/utobject.c | 677 +++++++++++++++++ drivers/acpi/acpica/utresrc.c | 616 +++++++++++++++ drivers/acpi/acpica/utstate.c | 347 +++++++++ drivers/acpi/acpica/utxface.c | 512 +++++++++++++ drivers/acpi/dispatcher/Makefile | 9 - drivers/acpi/dispatcher/dsfield.c | 650 ---------------- drivers/acpi/dispatcher/dsinit.c | 205 ----- drivers/acpi/dispatcher/dsmethod.c | 629 --------------- drivers/acpi/dispatcher/dsmthdat.c | 718 ------------------ drivers/acpi/dispatcher/dsobject.c | 813 -------------------- drivers/acpi/dispatcher/dsopcode.c | 1469 ------------------------------------ drivers/acpi/dispatcher/dsutils.c | 869 --------------------- drivers/acpi/dispatcher/dswexec.c | 746 ------------------ drivers/acpi/dispatcher/dswload.c | 1203 ----------------------------- drivers/acpi/dispatcher/dswscope.c | 214 ------ drivers/acpi/dispatcher/dswstate.c | 753 ------------------ drivers/acpi/events/Makefile | 9 - drivers/acpi/events/evevent.c | 313 -------- drivers/acpi/events/evgpe.c | 722 ------------------ drivers/acpi/events/evgpeblk.c | 1227 ------------------------------ drivers/acpi/events/evmisc.c | 621 --------------- drivers/acpi/events/evregion.c | 1070 -------------------------- drivers/acpi/events/evrgnini.c | 684 ----------------- drivers/acpi/events/evsci.c | 183 ----- drivers/acpi/events/evxface.c | 821 -------------------- drivers/acpi/events/evxfevnt.c | 871 --------------------- drivers/acpi/events/evxfregn.c | 254 ------- drivers/acpi/executer/Makefile | 10 - drivers/acpi/executer/exconfig.c | 536 ------------- drivers/acpi/executer/exconvrt.c | 692 ----------------- drivers/acpi/executer/excreate.c | 522 ------------- drivers/acpi/executer/exdump.c | 1060 -------------------------- drivers/acpi/executer/exfield.c | 340 --------- drivers/acpi/executer/exfldio.c | 961 ----------------------- drivers/acpi/executer/exmisc.c | 726 ------------------ drivers/acpi/executer/exmutex.c | 474 ------------ drivers/acpi/executer/exnames.c | 436 ----------- drivers/acpi/executer/exoparg1.c | 1050 -------------------------- drivers/acpi/executer/exoparg2.c | 605 --------------- drivers/acpi/executer/exoparg3.c | 273 ------- drivers/acpi/executer/exoparg6.c | 341 --------- drivers/acpi/executer/exprep.c | 590 --------------- drivers/acpi/executer/exregion.c | 499 ------------ drivers/acpi/executer/exresnte.c | 278 ------- drivers/acpi/executer/exresolv.c | 551 -------------- drivers/acpi/executer/exresop.c | 701 ----------------- drivers/acpi/executer/exstore.c | 716 ------------------ drivers/acpi/executer/exstoren.c | 304 -------- drivers/acpi/executer/exstorob.c | 209 ----- drivers/acpi/executer/exsystem.c | 303 -------- drivers/acpi/executer/exutils.c | 421 ----------- drivers/acpi/hardware/Makefile | 9 - drivers/acpi/hardware/hwacpi.c | 185 ----- drivers/acpi/hardware/hwgpe.c | 469 ------------ drivers/acpi/hardware/hwregs.c | 353 --------- drivers/acpi/hardware/hwsleep.c | 629 --------------- drivers/acpi/hardware/hwtimer.c | 188 ----- drivers/acpi/hardware/hwxface.c | 593 --------------- drivers/acpi/main.c | 696 +++++++++++++++++ drivers/acpi/namespace/Makefile | 12 - drivers/acpi/namespace/nsaccess.c | 676 ----------------- drivers/acpi/namespace/nsalloc.c | 497 ------------ drivers/acpi/namespace/nsdump.c | 709 ----------------- drivers/acpi/namespace/nsdumpdv.c | 141 ---- drivers/acpi/namespace/nseval.c | 278 ------- drivers/acpi/namespace/nsinit.c | 593 --------------- drivers/acpi/namespace/nsload.c | 315 -------- drivers/acpi/namespace/nsnames.c | 265 ------- drivers/acpi/namespace/nsobject.c | 441 ----------- drivers/acpi/namespace/nsparse.c | 204 ----- drivers/acpi/namespace/nspredef.c | 1065 -------------------------- drivers/acpi/namespace/nssearch.c | 415 ---------- drivers/acpi/namespace/nsutils.c | 997 ------------------------ drivers/acpi/namespace/nswalk.c | 296 -------- drivers/acpi/namespace/nsxfeval.c | 812 -------------------- drivers/acpi/namespace/nsxfname.c | 360 --------- drivers/acpi/namespace/nsxfobj.c | 287 ------- drivers/acpi/parser/Makefile | 8 - drivers/acpi/parser/psargs.c | 752 ------------------ drivers/acpi/parser/psloop.c | 1088 -------------------------- drivers/acpi/parser/psopcode.c | 810 -------------------- drivers/acpi/parser/psparse.c | 701 ----------------- drivers/acpi/parser/psscope.c | 265 ------- drivers/acpi/parser/pstree.c | 312 -------- drivers/acpi/parser/psutils.c | 244 ------ drivers/acpi/parser/pswalk.c | 110 --- drivers/acpi/parser/psxface.c | 385 ---------- drivers/acpi/proc.c | 520 +++++++++++++ drivers/acpi/resources/Makefile | 10 - drivers/acpi/resources/rsaddr.c | 381 ---------- drivers/acpi/resources/rscalc.c | 618 --------------- drivers/acpi/resources/rscreate.c | 468 ------------ drivers/acpi/resources/rsdump.c | 771 ------------------- drivers/acpi/resources/rsinfo.c | 206 ----- drivers/acpi/resources/rsio.c | 290 ------- drivers/acpi/resources/rsirq.c | 266 ------- drivers/acpi/resources/rslist.c | 203 ----- drivers/acpi/resources/rsmemory.c | 236 ------ drivers/acpi/resources/rsmisc.c | 561 -------------- drivers/acpi/resources/rsutils.c | 727 ------------------ drivers/acpi/resources/rsxface.c | 571 -------------- drivers/acpi/sleep.h | 7 + drivers/acpi/sleep/Makefile | 5 - drivers/acpi/sleep/main.c | 696 ----------------- drivers/acpi/sleep/proc.c | 520 ------------- drivers/acpi/sleep/sleep.h | 7 - drivers/acpi/sleep/wakeup.c | 167 ---- drivers/acpi/tables/Makefile | 7 - drivers/acpi/tables/tbfadt.c | 610 --------------- drivers/acpi/tables/tbfind.c | 140 ---- drivers/acpi/tables/tbinstal.c | 574 -------------- drivers/acpi/tables/tbutils.c | 582 -------------- drivers/acpi/tables/tbxface.c | 735 ------------------ drivers/acpi/tables/tbxfroot.c | 274 ------- drivers/acpi/utilities/Makefile | 9 - drivers/acpi/utilities/utalloc.c | 383 ---------- drivers/acpi/utilities/utcopy.c | 970 ------------------------ drivers/acpi/utilities/utdebug.c | 651 ---------------- drivers/acpi/utilities/utdelete.c | 677 ----------------- drivers/acpi/utilities/uteval.c | 752 ------------------ drivers/acpi/utilities/utglobal.c | 823 -------------------- drivers/acpi/utilities/utinit.c | 152 ---- drivers/acpi/utilities/utmath.c | 312 -------- drivers/acpi/utilities/utmisc.c | 1093 --------------------------- drivers/acpi/utilities/utmutex.c | 342 --------- drivers/acpi/utilities/utobject.c | 677 ----------------- drivers/acpi/utilities/utresrc.c | 616 --------------- drivers/acpi/utilities/utstate.c | 347 --------- drivers/acpi/utilities/utxface.c | 512 ------------- drivers/acpi/wakeup.c | 167 ++++ 236 files changed, 61021 insertions(+), 61069 deletions(-) create mode 100644 drivers/acpi/acpica/Makefile create mode 100644 drivers/acpi/acpica/dsfield.c create mode 100644 drivers/acpi/acpica/dsinit.c create mode 100644 drivers/acpi/acpica/dsmethod.c create mode 100644 drivers/acpi/acpica/dsmthdat.c create mode 100644 drivers/acpi/acpica/dsobject.c create mode 100644 drivers/acpi/acpica/dsopcode.c create mode 100644 drivers/acpi/acpica/dsutils.c create mode 100644 drivers/acpi/acpica/dswexec.c create mode 100644 drivers/acpi/acpica/dswload.c create mode 100644 drivers/acpi/acpica/dswscope.c create mode 100644 drivers/acpi/acpica/dswstate.c create mode 100644 drivers/acpi/acpica/evevent.c create mode 100644 drivers/acpi/acpica/evgpe.c create mode 100644 drivers/acpi/acpica/evgpeblk.c create mode 100644 drivers/acpi/acpica/evmisc.c create mode 100644 drivers/acpi/acpica/evregion.c create mode 100644 drivers/acpi/acpica/evrgnini.c create mode 100644 drivers/acpi/acpica/evsci.c create mode 100644 drivers/acpi/acpica/evxface.c create mode 100644 drivers/acpi/acpica/evxfevnt.c create mode 100644 drivers/acpi/acpica/evxfregn.c create mode 100644 drivers/acpi/acpica/exconfig.c create mode 100644 drivers/acpi/acpica/exconvrt.c create mode 100644 drivers/acpi/acpica/excreate.c create mode 100644 drivers/acpi/acpica/exdump.c create mode 100644 drivers/acpi/acpica/exfield.c create mode 100644 drivers/acpi/acpica/exfldio.c create mode 100644 drivers/acpi/acpica/exmisc.c create mode 100644 drivers/acpi/acpica/exmutex.c create mode 100644 drivers/acpi/acpica/exnames.c create mode 100644 drivers/acpi/acpica/exoparg1.c create mode 100644 drivers/acpi/acpica/exoparg2.c create mode 100644 drivers/acpi/acpica/exoparg3.c create mode 100644 drivers/acpi/acpica/exoparg6.c create mode 100644 drivers/acpi/acpica/exprep.c create mode 100644 drivers/acpi/acpica/exregion.c create mode 100644 drivers/acpi/acpica/exresnte.c create mode 100644 drivers/acpi/acpica/exresolv.c create mode 100644 drivers/acpi/acpica/exresop.c create mode 100644 drivers/acpi/acpica/exstore.c create mode 100644 drivers/acpi/acpica/exstoren.c create mode 100644 drivers/acpi/acpica/exstorob.c create mode 100644 drivers/acpi/acpica/exsystem.c create mode 100644 drivers/acpi/acpica/exutils.c create mode 100644 drivers/acpi/acpica/hwacpi.c create mode 100644 drivers/acpi/acpica/hwgpe.c create mode 100644 drivers/acpi/acpica/hwregs.c create mode 100644 drivers/acpi/acpica/hwsleep.c create mode 100644 drivers/acpi/acpica/hwtimer.c create mode 100644 drivers/acpi/acpica/hwxface.c create mode 100644 drivers/acpi/acpica/nsaccess.c create mode 100644 drivers/acpi/acpica/nsalloc.c create mode 100644 drivers/acpi/acpica/nsdump.c create mode 100644 drivers/acpi/acpica/nsdumpdv.c create mode 100644 drivers/acpi/acpica/nseval.c create mode 100644 drivers/acpi/acpica/nsinit.c create mode 100644 drivers/acpi/acpica/nsload.c create mode 100644 drivers/acpi/acpica/nsnames.c create mode 100644 drivers/acpi/acpica/nsobject.c create mode 100644 drivers/acpi/acpica/nsparse.c create mode 100644 drivers/acpi/acpica/nspredef.c create mode 100644 drivers/acpi/acpica/nssearch.c create mode 100644 drivers/acpi/acpica/nsutils.c create mode 100644 drivers/acpi/acpica/nswalk.c create mode 100644 drivers/acpi/acpica/nsxfeval.c create mode 100644 drivers/acpi/acpica/nsxfname.c create mode 100644 drivers/acpi/acpica/nsxfobj.c create mode 100644 drivers/acpi/acpica/psargs.c create mode 100644 drivers/acpi/acpica/psloop.c create mode 100644 drivers/acpi/acpica/psopcode.c create mode 100644 drivers/acpi/acpica/psparse.c create mode 100644 drivers/acpi/acpica/psscope.c create mode 100644 drivers/acpi/acpica/pstree.c create mode 100644 drivers/acpi/acpica/psutils.c create mode 100644 drivers/acpi/acpica/pswalk.c create mode 100644 drivers/acpi/acpica/psxface.c create mode 100644 drivers/acpi/acpica/rsaddr.c create mode 100644 drivers/acpi/acpica/rscalc.c create mode 100644 drivers/acpi/acpica/rscreate.c create mode 100644 drivers/acpi/acpica/rsdump.c create mode 100644 drivers/acpi/acpica/rsinfo.c create mode 100644 drivers/acpi/acpica/rsio.c create mode 100644 drivers/acpi/acpica/rsirq.c create mode 100644 drivers/acpi/acpica/rslist.c create mode 100644 drivers/acpi/acpica/rsmemory.c create mode 100644 drivers/acpi/acpica/rsmisc.c create mode 100644 drivers/acpi/acpica/rsutils.c create mode 100644 drivers/acpi/acpica/rsxface.c create mode 100644 drivers/acpi/acpica/tbfadt.c create mode 100644 drivers/acpi/acpica/tbfind.c create mode 100644 drivers/acpi/acpica/tbinstal.c create mode 100644 drivers/acpi/acpica/tbutils.c create mode 100644 drivers/acpi/acpica/tbxface.c create mode 100644 drivers/acpi/acpica/tbxfroot.c create mode 100644 drivers/acpi/acpica/utalloc.c create mode 100644 drivers/acpi/acpica/utcopy.c create mode 100644 drivers/acpi/acpica/utdebug.c create mode 100644 drivers/acpi/acpica/utdelete.c create mode 100644 drivers/acpi/acpica/uteval.c create mode 100644 drivers/acpi/acpica/utglobal.c create mode 100644 drivers/acpi/acpica/utinit.c create mode 100644 drivers/acpi/acpica/utmath.c create mode 100644 drivers/acpi/acpica/utmisc.c create mode 100644 drivers/acpi/acpica/utmutex.c create mode 100644 drivers/acpi/acpica/utobject.c create mode 100644 drivers/acpi/acpica/utresrc.c create mode 100644 drivers/acpi/acpica/utstate.c create mode 100644 drivers/acpi/acpica/utxface.c delete mode 100644 drivers/acpi/dispatcher/Makefile delete mode 100644 drivers/acpi/dispatcher/dsfield.c delete mode 100644 drivers/acpi/dispatcher/dsinit.c delete mode 100644 drivers/acpi/dispatcher/dsmethod.c delete mode 100644 drivers/acpi/dispatcher/dsmthdat.c delete mode 100644 drivers/acpi/dispatcher/dsobject.c delete mode 100644 drivers/acpi/dispatcher/dsopcode.c delete mode 100644 drivers/acpi/dispatcher/dsutils.c delete mode 100644 drivers/acpi/dispatcher/dswexec.c delete mode 100644 drivers/acpi/dispatcher/dswload.c delete mode 100644 drivers/acpi/dispatcher/dswscope.c delete mode 100644 drivers/acpi/dispatcher/dswstate.c delete mode 100644 drivers/acpi/events/Makefile delete mode 100644 drivers/acpi/events/evevent.c delete mode 100644 drivers/acpi/events/evgpe.c delete mode 100644 drivers/acpi/events/evgpeblk.c delete mode 100644 drivers/acpi/events/evmisc.c delete mode 100644 drivers/acpi/events/evregion.c delete mode 100644 drivers/acpi/events/evrgnini.c delete mode 100644 drivers/acpi/events/evsci.c delete mode 100644 drivers/acpi/events/evxface.c delete mode 100644 drivers/acpi/events/evxfevnt.c delete mode 100644 drivers/acpi/events/evxfregn.c delete mode 100644 drivers/acpi/executer/Makefile delete mode 100644 drivers/acpi/executer/exconfig.c delete mode 100644 drivers/acpi/executer/exconvrt.c delete mode 100644 drivers/acpi/executer/excreate.c delete mode 100644 drivers/acpi/executer/exdump.c delete mode 100644 drivers/acpi/executer/exfield.c delete mode 100644 drivers/acpi/executer/exfldio.c delete mode 100644 drivers/acpi/executer/exmisc.c delete mode 100644 drivers/acpi/executer/exmutex.c delete mode 100644 drivers/acpi/executer/exnames.c delete mode 100644 drivers/acpi/executer/exoparg1.c delete mode 100644 drivers/acpi/executer/exoparg2.c delete mode 100644 drivers/acpi/executer/exoparg3.c delete mode 100644 drivers/acpi/executer/exoparg6.c delete mode 100644 drivers/acpi/executer/exprep.c delete mode 100644 drivers/acpi/executer/exregion.c delete mode 100644 drivers/acpi/executer/exresnte.c delete mode 100644 drivers/acpi/executer/exresolv.c delete mode 100644 drivers/acpi/executer/exresop.c delete mode 100644 drivers/acpi/executer/exstore.c delete mode 100644 drivers/acpi/executer/exstoren.c delete mode 100644 drivers/acpi/executer/exstorob.c delete mode 100644 drivers/acpi/executer/exsystem.c delete mode 100644 drivers/acpi/executer/exutils.c delete mode 100644 drivers/acpi/hardware/Makefile delete mode 100644 drivers/acpi/hardware/hwacpi.c delete mode 100644 drivers/acpi/hardware/hwgpe.c delete mode 100644 drivers/acpi/hardware/hwregs.c delete mode 100644 drivers/acpi/hardware/hwsleep.c delete mode 100644 drivers/acpi/hardware/hwtimer.c delete mode 100644 drivers/acpi/hardware/hwxface.c create mode 100644 drivers/acpi/main.c delete mode 100644 drivers/acpi/namespace/Makefile delete mode 100644 drivers/acpi/namespace/nsaccess.c delete mode 100644 drivers/acpi/namespace/nsalloc.c delete mode 100644 drivers/acpi/namespace/nsdump.c delete mode 100644 drivers/acpi/namespace/nsdumpdv.c delete mode 100644 drivers/acpi/namespace/nseval.c delete mode 100644 drivers/acpi/namespace/nsinit.c delete mode 100644 drivers/acpi/namespace/nsload.c delete mode 100644 drivers/acpi/namespace/nsnames.c delete mode 100644 drivers/acpi/namespace/nsobject.c delete mode 100644 drivers/acpi/namespace/nsparse.c delete mode 100644 drivers/acpi/namespace/nspredef.c delete mode 100644 drivers/acpi/namespace/nssearch.c delete mode 100644 drivers/acpi/namespace/nsutils.c delete mode 100644 drivers/acpi/namespace/nswalk.c delete mode 100644 drivers/acpi/namespace/nsxfeval.c delete mode 100644 drivers/acpi/namespace/nsxfname.c delete mode 100644 drivers/acpi/namespace/nsxfobj.c delete mode 100644 drivers/acpi/parser/Makefile delete mode 100644 drivers/acpi/parser/psargs.c delete mode 100644 drivers/acpi/parser/psloop.c delete mode 100644 drivers/acpi/parser/psopcode.c delete mode 100644 drivers/acpi/parser/psparse.c delete mode 100644 drivers/acpi/parser/psscope.c delete mode 100644 drivers/acpi/parser/pstree.c delete mode 100644 drivers/acpi/parser/psutils.c delete mode 100644 drivers/acpi/parser/pswalk.c delete mode 100644 drivers/acpi/parser/psxface.c create mode 100644 drivers/acpi/proc.c delete mode 100644 drivers/acpi/resources/Makefile delete mode 100644 drivers/acpi/resources/rsaddr.c delete mode 100644 drivers/acpi/resources/rscalc.c delete mode 100644 drivers/acpi/resources/rscreate.c delete mode 100644 drivers/acpi/resources/rsdump.c delete mode 100644 drivers/acpi/resources/rsinfo.c delete mode 100644 drivers/acpi/resources/rsio.c delete mode 100644 drivers/acpi/resources/rsirq.c delete mode 100644 drivers/acpi/resources/rslist.c delete mode 100644 drivers/acpi/resources/rsmemory.c delete mode 100644 drivers/acpi/resources/rsmisc.c delete mode 100644 drivers/acpi/resources/rsutils.c delete mode 100644 drivers/acpi/resources/rsxface.c create mode 100644 drivers/acpi/sleep.h delete mode 100644 drivers/acpi/sleep/Makefile delete mode 100644 drivers/acpi/sleep/main.c delete mode 100644 drivers/acpi/sleep/proc.c delete mode 100644 drivers/acpi/sleep/sleep.h delete mode 100644 drivers/acpi/sleep/wakeup.c delete mode 100644 drivers/acpi/tables/Makefile delete mode 100644 drivers/acpi/tables/tbfadt.c delete mode 100644 drivers/acpi/tables/tbfind.c delete mode 100644 drivers/acpi/tables/tbinstal.c delete mode 100644 drivers/acpi/tables/tbutils.c delete mode 100644 drivers/acpi/tables/tbxface.c delete mode 100644 drivers/acpi/tables/tbxfroot.c delete mode 100644 drivers/acpi/utilities/Makefile delete mode 100644 drivers/acpi/utilities/utalloc.c delete mode 100644 drivers/acpi/utilities/utcopy.c delete mode 100644 drivers/acpi/utilities/utdebug.c delete mode 100644 drivers/acpi/utilities/utdelete.c delete mode 100644 drivers/acpi/utilities/uteval.c delete mode 100644 drivers/acpi/utilities/utglobal.c delete mode 100644 drivers/acpi/utilities/utinit.c delete mode 100644 drivers/acpi/utilities/utmath.c delete mode 100644 drivers/acpi/utilities/utmisc.c delete mode 100644 drivers/acpi/utilities/utmutex.c delete mode 100644 drivers/acpi/utilities/utobject.c delete mode 100644 drivers/acpi/utilities/utresrc.c delete mode 100644 drivers/acpi/utilities/utstate.c delete mode 100644 drivers/acpi/utilities/utxface.c create mode 100644 drivers/acpi/wakeup.c (limited to 'drivers/acpi/namespace/nsnames.c') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 3c0c93300f12..5d23c13ac7d4 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -2,15 +2,8 @@ # Makefile for the Linux ACPI interpreter # -export ACPI_CFLAGS - -ACPI_CFLAGS := -Os - -ifdef CONFIG_ACPI_DEBUG - ACPI_CFLAGS += -DACPI_DEBUG_OUTPUT -endif - -EXTRA_CFLAGS += $(ACPI_CFLAGS) +ccflags-y := -Os +ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT # # ACPI Boot-Time Table Parsing @@ -22,9 +15,13 @@ obj-$(CONFIG_X86) += blacklist.o # ACPI Core Subsystem (Interpreter) # obj-y += osl.o utils.o reboot.o\ - dispatcher/ events/ executer/ hardware/ \ - namespace/ parser/ resources/ tables/ \ - utilities/ + acpica/ + +# sleep related files +obj-y += wakeup.o +obj-y += main.o +obj-$(CONFIG_ACPI_SLEEP) += proc.o + # # ACPI Bus and Device Drivers @@ -35,7 +32,6 @@ ifdef CONFIG_CPU_FREQ processor-objs += processor_perflib.o endif -obj-y += sleep/ obj-y += bus.o glue.o obj-y += scan.o # Keep EC driver first. Initialization of others depend on it. diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile new file mode 100644 index 000000000000..3f23298ee3fd --- /dev/null +++ b/drivers/acpi/acpica/Makefile @@ -0,0 +1,44 @@ +# +# Makefile for ACPICA Core interpreter +# + +ccflags-y := -Os +ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT + +obj-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \ + dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \ + dsinit.o + +obj-y += evevent.o evregion.o evsci.o evxfevnt.o \ + evmisc.o evrgnini.o evxface.o evxfregn.o \ + evgpe.o evgpeblk.o + +obj-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\ + exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\ + excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \ + exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o + +obj-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o + +obj-$(ACPI_FUTURE_USAGE) += hwtimer.o + +obj-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \ + nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ + nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ + nsparse.o nspredef.o + +obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o + +obj-y += psargs.o psparse.o psloop.o pstree.o pswalk.o \ + psopcode.o psscope.o psutils.o psxface.o + +obj-y += rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \ + rscalc.o rsirq.o rsmemory.o rsutils.o + +obj-$(ACPI_FUTURE_USAGE) += rsdump.o + +obj-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o + +obj-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ + utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ + utstate.o utmutex.o utobject.o utresrc.o diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c new file mode 100644 index 000000000000..5fbc24075b44 --- /dev/null +++ b/drivers/acpi/acpica/dsfield.c @@ -0,0 +1,650 @@ +/****************************************************************************** + * + * Module Name: dsfield - Dispatcher field routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dsfield") + +/* Local prototypes */ +static acpi_status +acpi_ds_get_field_names(struct acpi_create_field_info *info, + struct acpi_walk_state *walk_state, + union acpi_parse_object *arg); + +/******************************************************************************* + * + * FUNCTION: acpi_ds_create_buffer_field + * + * PARAMETERS: Op - Current parse op (create_xXField) + * walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Execute the create_field operators: + * create_bit_field_op, + * create_byte_field_op, + * create_word_field_op, + * create_dword_field_op, + * create_qword_field_op, + * create_field_op (all of which define a field in a buffer) + * + ******************************************************************************/ + +acpi_status +acpi_ds_create_buffer_field(union acpi_parse_object *op, + struct acpi_walk_state *walk_state) +{ + union acpi_parse_object *arg; + struct acpi_namespace_node *node; + acpi_status status; + union acpi_operand_object *obj_desc; + union acpi_operand_object *second_desc = NULL; + u32 flags; + + ACPI_FUNCTION_TRACE(ds_create_buffer_field); + + /* + * Get the name_string argument (name of the new buffer_field) + */ + if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { + + /* For create_field, name is the 4th argument */ + + arg = acpi_ps_get_arg(op, 3); + } else { + /* For all other create_xXXField operators, name is the 3rd argument */ + + arg = acpi_ps_get_arg(op, 2); + } + + if (!arg) { + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + if (walk_state->deferred_node) { + node = walk_state->deferred_node; + status = AE_OK; + } else { + /* Execute flag should always be set when this function is entered */ + + if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + /* Creating new namespace node, should not already exist */ + + flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | + ACPI_NS_ERROR_IF_FOUND; + + /* Mark node temporary if we are executing a method */ + + if (walk_state->method_node) { + flags |= ACPI_NS_TEMPORARY; + } + + /* Enter the name_string into the namespace */ + + status = + acpi_ns_lookup(walk_state->scope_info, + arg->common.value.string, ACPI_TYPE_ANY, + ACPI_IMODE_LOAD_PASS1, flags, walk_state, + &node); + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(arg->common.value.string, status); + return_ACPI_STATUS(status); + } + } + + /* + * We could put the returned object (Node) on the object stack for later, + * but for now, we will put it in the "op" object that the parser uses, + * so we can get it again at the end of this scope. + */ + op->common.node = node; + + /* + * If there is no object attached to the node, this node was just created + * and we need to create the field object. Otherwise, this was a lookup + * of an existing node and we don't want to create the field object again. + */ + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + return_ACPI_STATUS(AE_OK); + } + + /* + * The Field definition is not fully parsed at this time. + * (We must save the address of the AML for the buffer and index operands) + */ + + /* Create the buffer field object */ + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Remember location in AML stream of the field unit opcode and operands -- + * since the buffer and index operands must be evaluated. + */ + second_desc = obj_desc->common.next_object; + second_desc->extra.aml_start = op->named.data; + second_desc->extra.aml_length = op->named.length; + obj_desc->buffer_field.node = node; + + /* Attach constructed field descriptors to parent node */ + + status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + cleanup: + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_field_names + * + * PARAMETERS: Info - create_field info structure + * ` walk_state - Current method state + * Arg - First parser arg for the field name list + * + * RETURN: Status + * + * DESCRIPTION: Process all named fields in a field declaration. Names are + * entered into the namespace. + * + ******************************************************************************/ + +static acpi_status +acpi_ds_get_field_names(struct acpi_create_field_info *info, + struct acpi_walk_state *walk_state, + union acpi_parse_object *arg) +{ + acpi_status status; + acpi_integer position; + + ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); + + /* First field starts at bit zero */ + + info->field_bit_position = 0; + + /* Process all elements in the field list (of parse nodes) */ + + while (arg) { + /* + * Three types of field elements are handled: + * 1) Offset - specifies a bit offset + * 2) access_as - changes the access mode + * 3) Name - Enters a new named field into the namespace + */ + switch (arg->common.aml_opcode) { + case AML_INT_RESERVEDFIELD_OP: + + position = (acpi_integer) info->field_bit_position + + (acpi_integer) arg->common.value.size; + + if (position > ACPI_UINT32_MAX) { + ACPI_ERROR((AE_INFO, + "Bit offset within field too large (> 0xFFFFFFFF)")); + return_ACPI_STATUS(AE_SUPPORT); + } + + info->field_bit_position = (u32) position; + break; + + case AML_INT_ACCESSFIELD_OP: + + /* + * Get a new access_type and access_attribute -- to be used for all + * field units that follow, until field end or another access_as + * keyword. + * + * In field_flags, preserve the flag bits other than the + * ACCESS_TYPE bits + */ + info->field_flags = (u8) + ((info-> + field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | + ((u8) ((u32) arg->common.value.integer >> 8))); + + info->attribute = (u8) (arg->common.value.integer); + break; + + case AML_INT_NAMEDFIELD_OP: + + /* Lookup the name, it should already exist */ + + status = acpi_ns_lookup(walk_state->scope_info, + (char *)&arg->named.name, + info->field_type, + ACPI_IMODE_EXECUTE, + ACPI_NS_DONT_OPEN_SCOPE, + walk_state, &info->field_node); + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE((char *)&arg->named.name, + status); + return_ACPI_STATUS(status); + } else { + arg->common.node = info->field_node; + info->field_bit_length = arg->common.value.size; + + /* + * If there is no object attached to the node, this node was + * just created and we need to create the field object. + * Otherwise, this was a lookup of an existing node and we + * don't want to create the field object again. + */ + if (!acpi_ns_get_attached_object + (info->field_node)) { + status = acpi_ex_prep_field_value(info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + } + + /* Keep track of bit position for the next field */ + + position = (acpi_integer) info->field_bit_position + + (acpi_integer) arg->common.value.size; + + if (position > ACPI_UINT32_MAX) { + ACPI_ERROR((AE_INFO, + "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)", + ACPI_CAST_PTR(char, + &info->field_node-> + name))); + return_ACPI_STATUS(AE_SUPPORT); + } + + info->field_bit_position += info->field_bit_length; + break; + + default: + + ACPI_ERROR((AE_INFO, + "Invalid opcode in field list: %X", + arg->common.aml_opcode)); + return_ACPI_STATUS(AE_AML_BAD_OPCODE); + } + + arg = arg->common.next; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_create_field + * + * PARAMETERS: Op - Op containing the Field definition and args + * region_node - Object for the containing Operation Region + * ` walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Create a new field in the specified operation region + * + ******************************************************************************/ + +acpi_status +acpi_ds_create_field(union acpi_parse_object *op, + struct acpi_namespace_node *region_node, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_parse_object *arg; + struct acpi_create_field_info info; + + ACPI_FUNCTION_TRACE_PTR(ds_create_field, op); + + /* First arg is the name of the parent op_region (must already exist) */ + + arg = op->common.value.arg; + if (!region_node) { + status = + acpi_ns_lookup(walk_state->scope_info, + arg->common.value.name, ACPI_TYPE_REGION, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, + walk_state, ®ion_node); + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(arg->common.value.name, status); + return_ACPI_STATUS(status); + } + } + + /* Second arg is the field flags */ + + arg = arg->common.next; + info.field_flags = (u8) arg->common.value.integer; + info.attribute = 0; + + /* Each remaining arg is a Named Field */ + + info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD; + info.region_node = region_node; + + status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_init_field_objects + * + * PARAMETERS: Op - Op containing the Field definition and args + * ` walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: For each "Field Unit" name in the argument list that is + * part of the field declaration, enter the name into the + * namespace. + * + ******************************************************************************/ + +acpi_status +acpi_ds_init_field_objects(union acpi_parse_object *op, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_parse_object *arg = NULL; + struct acpi_namespace_node *node; + u8 type = 0; + u32 flags; + + ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); + + /* Execute flag should always be set when this function is entered */ + + if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { + if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { + + /* bank_field Op is deferred, just return OK */ + + return_ACPI_STATUS(AE_OK); + } + + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + /* + * Get the field_list argument for this opcode. This is the start of the + * list of field elements. + */ + switch (walk_state->opcode) { + case AML_FIELD_OP: + arg = acpi_ps_get_arg(op, 2); + type = ACPI_TYPE_LOCAL_REGION_FIELD; + break; + + case AML_BANK_FIELD_OP: + arg = acpi_ps_get_arg(op, 4); + type = ACPI_TYPE_LOCAL_BANK_FIELD; + break; + + case AML_INDEX_FIELD_OP: + arg = acpi_ps_get_arg(op, 3); + type = ACPI_TYPE_LOCAL_INDEX_FIELD; + break; + + default: + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Creating new namespace node(s), should not already exist */ + + flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | + ACPI_NS_ERROR_IF_FOUND; + + /* Mark node(s) temporary if we are executing a method */ + + if (walk_state->method_node) { + flags |= ACPI_NS_TEMPORARY; + } + + /* + * Walk the list of entries in the field_list + * Note: field_list can be of zero length. In this case, Arg will be NULL. + */ + while (arg) { + /* + * Ignore OFFSET and ACCESSAS terms here; we are only interested in the + * field names in order to enter them into the namespace. + */ + if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { + status = acpi_ns_lookup(walk_state->scope_info, + (char *)&arg->named.name, type, + ACPI_IMODE_LOAD_PASS1, flags, + walk_state, &node); + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE((char *)&arg->named.name, + status); + if (status != AE_ALREADY_EXISTS) { + return_ACPI_STATUS(status); + } + + /* Name already exists, just ignore this error */ + + status = AE_OK; + } + + arg->common.node = node; + } + + /* Get the next field element in the list */ + + arg = arg->common.next; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_create_bank_field + * + * PARAMETERS: Op - Op containing the Field definition and args + * region_node - Object for the containing Operation Region + * walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Create a new bank field in the specified operation region + * + ******************************************************************************/ + +acpi_status +acpi_ds_create_bank_field(union acpi_parse_object *op, + struct acpi_namespace_node *region_node, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_parse_object *arg; + struct acpi_create_field_info info; + + ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op); + + /* First arg is the name of the parent op_region (must already exist) */ + + arg = op->common.value.arg; + if (!region_node) { + status = + acpi_ns_lookup(walk_state->scope_info, + arg->common.value.name, ACPI_TYPE_REGION, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, + walk_state, ®ion_node); + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(arg->common.value.name, status); + return_ACPI_STATUS(status); + } + } + + /* Second arg is the Bank Register (Field) (must already exist) */ + + arg = arg->common.next; + status = + acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, + &info.register_node); + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(arg->common.value.string, status); + return_ACPI_STATUS(status); + } + + /* + * Third arg is the bank_value + * This arg is a term_arg, not a constant + * It will be evaluated later, by acpi_ds_eval_bank_field_operands + */ + arg = arg->common.next; + + /* Fourth arg is the field flags */ + + arg = arg->common.next; + info.field_flags = (u8) arg->common.value.integer; + + /* Each remaining arg is a Named Field */ + + info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; + info.region_node = region_node; + + /* + * Use Info.data_register_node to store bank_field Op + * It's safe because data_register_node will never be used when create bank field + * We store aml_start and aml_length in the bank_field Op for late evaluation + * Used in acpi_ex_prep_field_value(Info) + * + * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"? + */ + info.data_register_node = (struct acpi_namespace_node *)op; + + status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_create_index_field + * + * PARAMETERS: Op - Op containing the Field definition and args + * region_node - Object for the containing Operation Region + * ` walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Create a new index field in the specified operation region + * + ******************************************************************************/ + +acpi_status +acpi_ds_create_index_field(union acpi_parse_object *op, + struct acpi_namespace_node *region_node, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_parse_object *arg; + struct acpi_create_field_info info; + + ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op); + + /* First arg is the name of the Index register (must already exist) */ + + arg = op->common.value.arg; + status = + acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, + &info.register_node); + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(arg->common.value.string, status); + return_ACPI_STATUS(status); + } + + /* Second arg is the data register (must already exist) */ + + arg = arg->common.next; + status = + acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, + &info.data_register_node); + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(arg->common.value.string, status); + return_ACPI_STATUS(status); + } + + /* Next arg is the field flags */ + + arg = arg->common.next; + info.field_flags = (u8) arg->common.value.integer; + + /* Each remaining arg is a Named Field */ + + info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD; + info.region_node = region_node; + + status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c new file mode 100644 index 000000000000..4f1cdd823fcc --- /dev/null +++ b/drivers/acpi/acpica/dsinit.c @@ -0,0 +1,205 @@ +/****************************************************************************** + * + * Module Name: dsinit - Object initialization namespace walk + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dsinit") + +/* Local prototypes */ +static acpi_status +acpi_ds_init_one_object(acpi_handle obj_handle, + u32 level, void *context, void **return_value); + +/******************************************************************************* + * + * FUNCTION: acpi_ds_init_one_object + * + * PARAMETERS: obj_handle - Node for the object + * Level - Current nesting level + * Context - Points to a init info struct + * return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object + * within the namespace. + * + * Currently, the only objects that require initialization are: + * 1) Methods + * 2) Operation Regions + * + ******************************************************************************/ + +static acpi_status +acpi_ds_init_one_object(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + struct acpi_init_walk_info *info = + (struct acpi_init_walk_info *)context; + struct acpi_namespace_node *node = + (struct acpi_namespace_node *)obj_handle; + acpi_object_type type; + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + /* + * We are only interested in NS nodes owned by the table that + * was just loaded + */ + if (node->owner_id != info->owner_id) { + return (AE_OK); + } + + info->object_count++; + + /* And even then, we are only interested in a few object types */ + + type = acpi_ns_get_type(obj_handle); + + switch (type) { + case ACPI_TYPE_REGION: + + status = acpi_ds_initialize_region(obj_handle); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During Region initialization %p [%4.4s]", + obj_handle, + acpi_ut_get_node_name(obj_handle))); + } + + info->op_region_count++; + break; + + case ACPI_TYPE_METHOD: + + info->method_count++; + break; + + case ACPI_TYPE_DEVICE: + + info->device_count++; + break; + + default: + break; + } + + /* + * We ignore errors from above, and always return OK, since + * we don't want to abort the walk on a single error. + */ + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_initialize_objects + * + * PARAMETERS: table_desc - Descriptor for parent ACPI table + * start_node - Root of subtree to be initialized. + * + * RETURN: Status + * + * DESCRIPTION: Walk the namespace starting at "StartNode" and perform any + * necessary initialization on the objects found therein + * + ******************************************************************************/ + +acpi_status +acpi_ds_initialize_objects(u32 table_index, + struct acpi_namespace_node * start_node) +{ + acpi_status status; + struct acpi_init_walk_info info; + struct acpi_table_header *table; + acpi_owner_id owner_id; + + ACPI_FUNCTION_TRACE(ds_initialize_objects); + + status = acpi_tb_get_owner_id(table_index, &owner_id); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "**** Starting initialization of namespace objects ****\n")); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Parsing all Control Methods:")); + + info.method_count = 0; + info.op_region_count = 0; + info.object_count = 0; + info.device_count = 0; + info.table_index = table_index; + info.owner_id = owner_id; + + /* Walk entire namespace from the supplied root */ + + status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, + acpi_ds_init_one_object, &info, NULL); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); + } + + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n", + table->signature, owner_id, info.object_count, + info.device_count, info.method_count, + info.op_region_count)); + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "%hd Methods, %hd Regions\n", info.method_count, + info.op_region_count)); + + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c new file mode 100644 index 000000000000..333c8560d9f8 --- /dev/null +++ b/drivers/acpi/acpica/dsmethod.c @@ -0,0 +1,629 @@ +/****************************************************************************** + * + * Module Name: dsmethod - Parser/Interpreter interface - control method parsing + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include +#ifdef ACPI_DISASSEMBLER +#include +#endif + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dsmethod") + +/* Local prototypes */ +static acpi_status +acpi_ds_create_method_mutex(union acpi_operand_object *method_desc); + +/******************************************************************************* + * + * FUNCTION: acpi_ds_method_error + * + * PARAMETERS: Status - Execution status + * walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Called on method error. Invoke the global exception handler if + * present, dump the method data if the disassembler is configured + * + * Note: Allows the exception handler to change the status code + * + ******************************************************************************/ + +acpi_status +acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) +{ + ACPI_FUNCTION_ENTRY(); + + /* Ignore AE_OK and control exception codes */ + + if (ACPI_SUCCESS(status) || (status & AE_CODE_CONTROL)) { + return (status); + } + + /* Invoke the global exception handler */ + + if (acpi_gbl_exception_handler) { + + /* Exit the interpreter, allow handler to execute methods */ + + acpi_ex_exit_interpreter(); + + /* + * Handler can map the exception code to anything it wants, including + * AE_OK, in which case the executing method will not be aborted. + */ + status = acpi_gbl_exception_handler(status, + walk_state->method_node ? + walk_state->method_node-> + name.integer : 0, + walk_state->opcode, + walk_state->aml_offset, + NULL); + acpi_ex_enter_interpreter(); + } + + acpi_ds_clear_implicit_return(walk_state); + +#ifdef ACPI_DISASSEMBLER + if (ACPI_FAILURE(status)) { + + /* Display method locals/args if disassembler is present */ + + acpi_dm_dump_method_info(status, walk_state, walk_state->op); + } +#endif + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_create_method_mutex + * + * PARAMETERS: obj_desc - The method object + * + * RETURN: Status + * + * DESCRIPTION: Create a mutex object for a serialized control method + * + ******************************************************************************/ + +static acpi_status +acpi_ds_create_method_mutex(union acpi_operand_object *method_desc) +{ + union acpi_operand_object *mutex_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(ds_create_method_mutex); + + /* Create the new mutex object */ + + mutex_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX); + if (!mutex_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Create the actual OS Mutex */ + + status = acpi_os_create_mutex(&mutex_desc->mutex.os_mutex); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + mutex_desc->mutex.sync_level = method_desc->method.sync_level; + method_desc->method.mutex = mutex_desc; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_begin_method_execution + * + * PARAMETERS: method_node - Node of the method + * obj_desc - The method object + * walk_state - current state, NULL if not yet executing + * a method. + * + * RETURN: Status + * + * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, + * increments the thread count, and waits at the method semaphore + * for clearance to execute. + * + ******************************************************************************/ + +acpi_status +acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, + union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_PTR(ds_begin_method_execution, method_node); + + if (!method_node) { + return_ACPI_STATUS(AE_NULL_ENTRY); + } + + /* Prevent wraparound of thread count */ + + if (obj_desc->method.thread_count == ACPI_UINT8_MAX) { + ACPI_ERROR((AE_INFO, + "Method reached maximum reentrancy limit (255)")); + return_ACPI_STATUS(AE_AML_METHOD_LIMIT); + } + + /* + * If this method is serialized, we need to acquire the method mutex. + */ + if (obj_desc->method.method_flags & AML_METHOD_SERIALIZED) { + /* + * Create a mutex for the method if it is defined to be Serialized + * and a mutex has not already been created. We defer the mutex creation + * until a method is actually executed, to minimize the object count + */ + if (!obj_desc->method.mutex) { + status = acpi_ds_create_method_mutex(obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * The current_sync_level (per-thread) must be less than or equal to + * the sync level of the method. This mechanism provides some + * deadlock prevention + * + * Top-level method invocation has no walk state at this point + */ + if (walk_state && + (walk_state->thread->current_sync_level > + obj_desc->method.mutex->mutex.sync_level)) { + ACPI_ERROR((AE_INFO, + "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%d)", + acpi_ut_get_node_name(method_node), + walk_state->thread->current_sync_level)); + + return_ACPI_STATUS(AE_AML_MUTEX_ORDER); + } + + /* + * Obtain the method mutex if necessary. Do not acquire mutex for a + * recursive call. + */ + if (!walk_state || + !obj_desc->method.mutex->mutex.thread_id || + (walk_state->thread->thread_id != + obj_desc->method.mutex->mutex.thread_id)) { + /* + * Acquire the method mutex. This releases the interpreter if we + * block (and reacquires it before it returns) + */ + status = + acpi_ex_system_wait_mutex(obj_desc->method.mutex-> + mutex.os_mutex, + ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Update the mutex and walk info and save the original sync_level */ + + if (walk_state) { + obj_desc->method.mutex->mutex. + original_sync_level = + walk_state->thread->current_sync_level; + + obj_desc->method.mutex->mutex.thread_id = + walk_state->thread->thread_id; + walk_state->thread->current_sync_level = + obj_desc->method.sync_level; + } else { + obj_desc->method.mutex->mutex. + original_sync_level = + obj_desc->method.mutex->mutex.sync_level; + } + } + + /* Always increase acquisition depth */ + + obj_desc->method.mutex->mutex.acquisition_depth++; + } + + /* + * Allocate an Owner ID for this method, only if this is the first thread + * to begin concurrent execution. We only need one owner_id, even if the + * method is invoked recursively. + */ + if (!obj_desc->method.owner_id) { + status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + } + + /* + * Increment the method parse tree thread count since it has been + * reentered one more time (even if it is the same thread) + */ + obj_desc->method.thread_count++; + return_ACPI_STATUS(status); + + cleanup: + /* On error, must release the method mutex (if present) */ + + if (obj_desc->method.mutex) { + acpi_os_release_mutex(obj_desc->method.mutex->mutex.os_mutex); + } + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_call_control_method + * + * PARAMETERS: Thread - Info for this thread + * this_walk_state - Current walk state + * Op - Current Op to be walked + * + * RETURN: Status + * + * DESCRIPTION: Transfer execution to a called control method + * + ******************************************************************************/ + +acpi_status +acpi_ds_call_control_method(struct acpi_thread_state *thread, + struct acpi_walk_state *this_walk_state, + union acpi_parse_object *op) +{ + acpi_status status; + struct acpi_namespace_node *method_node; + struct acpi_walk_state *next_walk_state = NULL; + union acpi_operand_object *obj_desc; + struct acpi_evaluate_info *info; + u32 i; + + ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state); + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Calling method %p, currentstate=%p\n", + this_walk_state->prev_op, this_walk_state)); + + /* + * Get the namespace entry for the control method we are about to call + */ + method_node = this_walk_state->method_call_node; + if (!method_node) { + return_ACPI_STATUS(AE_NULL_ENTRY); + } + + obj_desc = acpi_ns_get_attached_object(method_node); + if (!obj_desc) { + return_ACPI_STATUS(AE_NULL_OBJECT); + } + + /* Init for new method, possibly wait on method mutex */ + + status = acpi_ds_begin_method_execution(method_node, obj_desc, + this_walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Begin method parse/execution. Create a new walk state */ + + next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, + NULL, obj_desc, thread); + if (!next_walk_state) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * The resolved arguments were put on the previous walk state's operand + * stack. Operands on the previous walk state stack always + * start at index 0. Also, null terminate the list of arguments + */ + this_walk_state->operands[this_walk_state->num_operands] = NULL; + + /* + * Allocate and initialize the evaluation information block + * TBD: this is somewhat inefficient, should change interface to + * ds_init_aml_walk. For now, keeps this struct off the CPU stack + */ + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->parameters = &this_walk_state->operands[0]; + + status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node, + obj_desc->method.aml_start, + obj_desc->method.aml_length, info, + ACPI_IMODE_EXECUTE); + + ACPI_FREE(info); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* + * Delete the operands on the previous walkstate operand stack + * (they were copied to new objects) + */ + for (i = 0; i < obj_desc->method.param_count; i++) { + acpi_ut_remove_reference(this_walk_state->operands[i]); + this_walk_state->operands[i] = NULL; + } + + /* Clear the operand stack */ + + this_walk_state->num_operands = 0; + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", + method_node->name.ascii, next_walk_state)); + + /* Invoke an internal method if necessary */ + + if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { + status = obj_desc->method.implementation(next_walk_state); + if (status == AE_OK) { + status = AE_CTRL_TERMINATE; + } + } + + return_ACPI_STATUS(status); + + cleanup: + + /* On error, we must terminate the method properly */ + + acpi_ds_terminate_control_method(obj_desc, next_walk_state); + if (next_walk_state) { + acpi_ds_delete_walk_state(next_walk_state); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_restart_control_method + * + * PARAMETERS: walk_state - State for preempted method (caller) + * return_desc - Return value from the called method + * + * RETURN: Status + * + * DESCRIPTION: Restart a method that was preempted by another (nested) method + * invocation. Handle the return value (if any) from the callee. + * + ******************************************************************************/ + +acpi_status +acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, + union acpi_operand_object *return_desc) +{ + acpi_status status; + int same_as_implicit_return; + + ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state); + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n", + acpi_ut_get_node_name(walk_state->method_node), + walk_state->method_call_op, return_desc)); + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n", + walk_state->return_used, + walk_state->results, walk_state)); + + /* Did the called method return a value? */ + + if (return_desc) { + + /* Is the implicit return object the same as the return desc? */ + + same_as_implicit_return = + (walk_state->implicit_return_obj == return_desc); + + /* Are we actually going to use the return value? */ + + if (walk_state->return_used) { + + /* Save the return value from the previous method */ + + status = acpi_ds_result_push(return_desc, walk_state); + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(return_desc); + return_ACPI_STATUS(status); + } + + /* + * Save as THIS method's return value in case it is returned + * immediately to yet another method + */ + walk_state->return_desc = return_desc; + } + + /* + * The following code is the optional support for the so-called + * "implicit return". Some AML code assumes that the last value of the + * method is "implicitly" returned to the caller, in the absence of an + * explicit return value. + * + * Just save the last result of the method as the return value. + * + * NOTE: this is optional because the ASL language does not actually + * support this behavior. + */ + else if (!acpi_ds_do_implicit_return + (return_desc, walk_state, FALSE) + || same_as_implicit_return) { + /* + * Delete the return value if it will not be used by the + * calling method or remove one reference if the explicit return + * is the same as the implicit return value. + */ + acpi_ut_remove_reference(return_desc); + } + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_terminate_control_method + * + * PARAMETERS: method_desc - Method object + * walk_state - State associated with the method + * + * RETURN: None + * + * DESCRIPTION: Terminate a control method. Delete everything that the method + * created, delete all locals and arguments, and delete the parse + * tree if requested. + * + * MUTEX: Interpreter is locked + * + ******************************************************************************/ + +void +acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, + struct acpi_walk_state *walk_state) +{ + + ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state); + + /* method_desc is required, walk_state is optional */ + + if (!method_desc) { + return_VOID; + } + + if (walk_state) { + + /* Delete all arguments and locals */ + + acpi_ds_method_data_delete_all(walk_state); + + /* + * If method is serialized, release the mutex and restore the + * current sync level for this thread + */ + if (method_desc->method.mutex) { + + /* Acquisition Depth handles recursive calls */ + + method_desc->method.mutex->mutex.acquisition_depth--; + if (!method_desc->method.mutex->mutex.acquisition_depth) { + walk_state->thread->current_sync_level = + method_desc->method.mutex->mutex. + original_sync_level; + + acpi_os_release_mutex(method_desc->method. + mutex->mutex.os_mutex); + method_desc->method.mutex->mutex.thread_id = NULL; + } + } + + /* + * Delete any namespace objects created anywhere within + * the namespace by the execution of this method + */ + acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id); + } + + /* Decrement the thread count on the method */ + + if (method_desc->method.thread_count) { + method_desc->method.thread_count--; + } else { + ACPI_ERROR((AE_INFO, "Invalid zero thread count in method")); + } + + /* Are there any other threads currently executing this method? */ + + if (method_desc->method.thread_count) { + /* + * Additional threads. Do not release the owner_id in this case, + * we immediately reuse it for the next thread executing this method + */ + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "*** Completed execution of one thread, %d threads remaining\n", + method_desc->method.thread_count)); + } else { + /* This is the only executing thread for this method */ + + /* + * Support to dynamically change a method from not_serialized to + * Serialized if it appears that the method is incorrectly written and + * does not support multiple thread execution. The best example of this + * is if such a method creates namespace objects and blocks. A second + * thread will fail with an AE_ALREADY_EXISTS exception + * + * This code is here because we must wait until the last thread exits + * before creating the synchronization semaphore. + */ + if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED) + && (!method_desc->method.mutex)) { + (void)acpi_ds_create_method_mutex(method_desc); + } + + /* No more threads, we can free the owner_id */ + + acpi_ut_release_owner_id(&method_desc->method.owner_id); + } + + return_VOID; +} diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c new file mode 100644 index 000000000000..a1a11996a651 --- /dev/null +++ b/drivers/acpi/acpica/dsmthdat.c @@ -0,0 +1,718 @@ +/******************************************************************************* + * + * Module Name: dsmthdat - control method arguments and local variables + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dsmthdat") + +/* Local prototypes */ +static void +acpi_ds_method_data_delete_value(u8 type, + u32 index, struct acpi_walk_state *walk_state); + +static acpi_status +acpi_ds_method_data_set_value(u8 type, + u32 index, + union acpi_operand_object *object, + struct acpi_walk_state *walk_state); + +#ifdef ACPI_OBSOLETE_FUNCTIONS +acpi_object_type +acpi_ds_method_data_get_type(u16 opcode, + u32 index, struct acpi_walk_state *walk_state); +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ds_method_data_init + * + * PARAMETERS: walk_state - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Initialize the data structures that hold the method's arguments + * and locals. The data struct is an array of namespace nodes for + * each - this allows ref_of and de_ref_of to work properly for these + * special data types. + * + * NOTES: walk_state fields are initialized to zero by the + * ACPI_ALLOCATE_ZEROED(). + * + * A pseudo-Namespace Node is assigned to each argument and local + * so that ref_of() can return a pointer to the Node. + * + ******************************************************************************/ + +void acpi_ds_method_data_init(struct acpi_walk_state *walk_state) +{ + u32 i; + + ACPI_FUNCTION_TRACE(ds_method_data_init); + + /* Init the method arguments */ + + for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) { + ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name, + NAMEOF_ARG_NTE); + walk_state->arguments[i].name.integer |= (i << 24); + walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED; + walk_state->arguments[i].type = ACPI_TYPE_ANY; + walk_state->arguments[i].flags = + ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG; + } + + /* Init the method locals */ + + for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) { + ACPI_MOVE_32_TO_32(&walk_state->local_variables[i].name, + NAMEOF_LOCAL_NTE); + + walk_state->local_variables[i].name.integer |= (i << 24); + walk_state->local_variables[i].descriptor_type = + ACPI_DESC_TYPE_NAMED; + walk_state->local_variables[i].type = ACPI_TYPE_ANY; + walk_state->local_variables[i].flags = + ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL; + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_method_data_delete_all + * + * PARAMETERS: walk_state - Current walk state object + * + * RETURN: None + * + * DESCRIPTION: Delete method locals and arguments. Arguments are only + * deleted if this method was called from another method. + * + ******************************************************************************/ + +void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state) +{ + u32 index; + + ACPI_FUNCTION_TRACE(ds_method_data_delete_all); + + /* Detach the locals */ + + for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) { + if (walk_state->local_variables[index].object) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Local%d=%p\n", + index, + walk_state->local_variables[index]. + object)); + + /* Detach object (if present) and remove a reference */ + + acpi_ns_detach_object(&walk_state-> + local_variables[index]); + } + } + + /* Detach the arguments */ + + for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) { + if (walk_state->arguments[index].object) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Arg%d=%p\n", + index, + walk_state->arguments[index].object)); + + /* Detach object (if present) and remove a reference */ + + acpi_ns_detach_object(&walk_state->arguments[index]); + } + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_method_data_init_args + * + * PARAMETERS: *Params - Pointer to a parameter list for the method + * max_param_count - The arg count for this method + * walk_state - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Initialize arguments for a method. The parameter list is a list + * of ACPI operand objects, either null terminated or whose length + * is defined by max_param_count. + * + ******************************************************************************/ + +acpi_status +acpi_ds_method_data_init_args(union acpi_operand_object **params, + u32 max_param_count, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + u32 index = 0; + + ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params); + + if (!params) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "No param list passed to method\n")); + return_ACPI_STATUS(AE_OK); + } + + /* Copy passed parameters into the new method stack frame */ + + while ((index < ACPI_METHOD_NUM_ARGS) && + (index < max_param_count) && params[index]) { + /* + * A valid parameter. + * Store the argument in the method/walk descriptor. + * Do not copy the arg in order to implement call by reference + */ + status = acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index, + params[index], + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + index++; + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%d args passed to method\n", index)); + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_method_data_get_node + * + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG + * Index - Which Local or Arg whose type to get + * walk_state - Current walk state object + * Node - Where the node is returned. + * + * RETURN: Status and node + * + * DESCRIPTION: Get the Node associated with a local or arg. + * + ******************************************************************************/ + +acpi_status +acpi_ds_method_data_get_node(u8 type, + u32 index, + struct acpi_walk_state *walk_state, + struct acpi_namespace_node **node) +{ + ACPI_FUNCTION_TRACE(ds_method_data_get_node); + + /* + * Method Locals and Arguments are supported + */ + switch (type) { + case ACPI_REFCLASS_LOCAL: + + if (index > ACPI_METHOD_MAX_LOCAL) { + ACPI_ERROR((AE_INFO, + "Local index %d is invalid (max %d)", + index, ACPI_METHOD_MAX_LOCAL)); + return_ACPI_STATUS(AE_AML_INVALID_INDEX); + } + + /* Return a pointer to the pseudo-node */ + + *node = &walk_state->local_variables[index]; + break; + + case ACPI_REFCLASS_ARG: + + if (index > ACPI_METHOD_MAX_ARG) { + ACPI_ERROR((AE_INFO, + "Arg index %d is invalid (max %d)", + index, ACPI_METHOD_MAX_ARG)); + return_ACPI_STATUS(AE_AML_INVALID_INDEX); + } + + /* Return a pointer to the pseudo-node */ + + *node = &walk_state->arguments[index]; + break; + + default: + ACPI_ERROR((AE_INFO, "Type %d is invalid", type)); + return_ACPI_STATUS(AE_TYPE); + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_method_data_set_value + * + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG + * Index - Which Local or Arg to get + * Object - Object to be inserted into the stack entry + * walk_state - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index. + * Note: There is no "implicit conversion" for locals. + * + ******************************************************************************/ + +static acpi_status +acpi_ds_method_data_set_value(u8 type, + u32 index, + union acpi_operand_object *object, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + struct acpi_namespace_node *node; + + ACPI_FUNCTION_TRACE(ds_method_data_set_value); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "NewObj %p Type %2.2X, Refs=%d [%s]\n", object, + type, object->common.reference_count, + acpi_ut_get_type_name(object->common.type))); + + /* Get the namespace node for the arg/local */ + + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Increment ref count so object can't be deleted while installed. + * NOTE: We do not copy the object in order to preserve the call by + * reference semantics of ACPI Control Method invocation. + * (See ACPI Specification 2.0_c) + */ + acpi_ut_add_reference(object); + + /* Install the object */ + + node->object = object; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_method_data_get_value + * + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG + * Index - Which local_var or argument to get + * walk_state - Current walk state object + * dest_desc - Where Arg or Local value is returned + * + * RETURN: Status + * + * DESCRIPTION: Retrieve value of selected Arg or Local for this method + * Used only in acpi_ex_resolve_to_value(). + * + ******************************************************************************/ + +acpi_status +acpi_ds_method_data_get_value(u8 type, + u32 index, + struct acpi_walk_state *walk_state, + union acpi_operand_object **dest_desc) +{ + acpi_status status; + struct acpi_namespace_node *node; + union acpi_operand_object *object; + + ACPI_FUNCTION_TRACE(ds_method_data_get_value); + + /* Validate the object descriptor */ + + if (!dest_desc) { + ACPI_ERROR((AE_INFO, "Null object descriptor pointer")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the namespace node for the arg/local */ + + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the object from the node */ + + object = node->object; + + /* Examine the returned object, it must be valid. */ + + if (!object) { + /* + * Index points to uninitialized object. + * This means that either 1) The expected argument was + * not passed to the method, or 2) A local variable + * was referenced by the method (via the ASL) + * before it was initialized. Either case is an error. + */ + + /* If slack enabled, init the local_x/arg_x to an Integer of value zero */ + + if (acpi_gbl_enable_interpreter_slack) { + object = + acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!object) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + object->integer.value = 0; + node->object = object; + } + + /* Otherwise, return the error */ + + else + switch (type) { + case ACPI_REFCLASS_ARG: + + ACPI_ERROR((AE_INFO, + "Uninitialized Arg[%d] at node %p", + index, node)); + + return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); + + case ACPI_REFCLASS_LOCAL: + + ACPI_ERROR((AE_INFO, + "Uninitialized Local[%d] at node %p", + index, node)); + + return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL); + + default: + + ACPI_ERROR((AE_INFO, + "Not a Arg/Local opcode: %X", + type)); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + } + + /* + * The Index points to an initialized and valid object. + * Return an additional reference to the object + */ + *dest_desc = object; + acpi_ut_add_reference(object); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_method_data_delete_value + * + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG + * Index - Which local_var or argument to delete + * walk_state - Current walk state object + * + * RETURN: None + * + * DESCRIPTION: Delete the entry at Opcode:Index. Inserts + * a null into the stack slot after the object is deleted. + * + ******************************************************************************/ + +static void +acpi_ds_method_data_delete_value(u8 type, + u32 index, struct acpi_walk_state *walk_state) +{ + acpi_status status; + struct acpi_namespace_node *node; + union acpi_operand_object *object; + + ACPI_FUNCTION_TRACE(ds_method_data_delete_value); + + /* Get the namespace node for the arg/local */ + + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); + if (ACPI_FAILURE(status)) { + return_VOID; + } + + /* Get the associated object */ + + object = acpi_ns_get_attached_object(node); + + /* + * Undefine the Arg or Local by setting its descriptor + * pointer to NULL. Locals/Args can contain both + * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs + */ + node->object = NULL; + + if ((object) && + (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_OPERAND)) { + /* + * There is a valid object. + * Decrement the reference count by one to balance the + * increment when the object was stored. + */ + acpi_ut_remove_reference(object); + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_store_object_to_local + * + * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * ACPI_REFCLASS_ARG + * Index - Which Local or Arg to set + * obj_desc - Value to be stored + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed + * as the new value for the Arg or Local and the reference count + * for obj_desc is incremented. + * + ******************************************************************************/ + +acpi_status +acpi_ds_store_object_to_local(u8 type, + u32 index, + union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + struct acpi_namespace_node *node; + union acpi_operand_object *current_obj_desc; + union acpi_operand_object *new_obj_desc; + + ACPI_FUNCTION_TRACE(ds_store_object_to_local); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%d Obj=%p\n", + type, index, obj_desc)); + + /* Parameter validation */ + + if (!obj_desc) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the namespace node for the arg/local */ + + status = acpi_ds_method_data_get_node(type, index, walk_state, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + current_obj_desc = acpi_ns_get_attached_object(node); + if (current_obj_desc == obj_desc) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n", + obj_desc)); + return_ACPI_STATUS(status); + } + + /* + * If the reference count on the object is more than one, we must + * take a copy of the object before we store. A reference count + * of exactly 1 means that the object was just created during the + * evaluation of an expression, and we can safely use it since it + * is not used anywhere else. + */ + new_obj_desc = obj_desc; + if (obj_desc->common.reference_count > 1) { + status = + acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * If there is an object already in this slot, we either + * have to delete it, or if this is an argument and there + * is an object reference stored there, we have to do + * an indirect store! + */ + if (current_obj_desc) { + /* + * Check for an indirect store if an argument + * contains an object reference (stored as an Node). + * We don't allow this automatic dereferencing for + * locals, since a store to a local should overwrite + * anything there, including an object reference. + * + * If both Arg0 and Local0 contain ref_of (Local4): + * + * Store (1, Arg0) - Causes indirect store to local4 + * Store (1, Local0) - Stores 1 in local0, overwriting + * the reference to local4 + * Store (1, de_refof (Local0)) - Causes indirect store to local4 + * + * Weird, but true. + */ + if (type == ACPI_REFCLASS_ARG) { + /* + * If we have a valid reference object that came from ref_of(), + * do the indirect store + */ + if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) == + ACPI_DESC_TYPE_OPERAND) + && (current_obj_desc->common.type == + ACPI_TYPE_LOCAL_REFERENCE) + && (current_obj_desc->reference.class == + ACPI_REFCLASS_REFOF)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Arg (%p) is an ObjRef(Node), storing in node %p\n", + new_obj_desc, + current_obj_desc)); + + /* + * Store this object to the Node (perform the indirect store) + * NOTE: No implicit conversion is performed, as per the ACPI + * specification rules on storing to Locals/Args. + */ + status = + acpi_ex_store_object_to_node(new_obj_desc, + current_obj_desc-> + reference. + object, + walk_state, + ACPI_NO_IMPLICIT_CONVERSION); + + /* Remove local reference if we copied the object above */ + + if (new_obj_desc != obj_desc) { + acpi_ut_remove_reference(new_obj_desc); + } + return_ACPI_STATUS(status); + } + } + + /* Delete the existing object before storing the new one */ + + acpi_ds_method_data_delete_value(type, index, walk_state); + } + + /* + * Install the Obj descriptor (*new_obj_desc) into + * the descriptor for the Arg or Local. + * (increments the object reference count by one) + */ + status = + acpi_ds_method_data_set_value(type, index, new_obj_desc, + walk_state); + + /* Remove local reference if we copied the object above */ + + if (new_obj_desc != obj_desc) { + acpi_ut_remove_reference(new_obj_desc); + } + + return_ACPI_STATUS(status); +} + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: acpi_ds_method_data_get_type + * + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * Index - Which Local or Arg whose type to get + * walk_state - Current walk state object + * + * RETURN: Data type of current value of the selected Arg or Local + * + * DESCRIPTION: Get the type of the object stored in the Local or Arg + * + ******************************************************************************/ + +acpi_object_type +acpi_ds_method_data_get_type(u16 opcode, + u32 index, struct acpi_walk_state *walk_state) +{ + acpi_status status; + struct acpi_namespace_node *node; + union acpi_operand_object *object; + + ACPI_FUNCTION_TRACE(ds_method_data_get_type); + + /* Get the namespace node for the arg/local */ + + status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); + if (ACPI_FAILURE(status)) { + return_VALUE((ACPI_TYPE_NOT_FOUND)); + } + + /* Get the object */ + + object = acpi_ns_get_attached_object(node); + if (!object) { + + /* Uninitialized local/arg, return TYPE_ANY */ + + return_VALUE(ACPI_TYPE_ANY); + } + + /* Get the object type */ + + return_VALUE(ACPI_GET_OBJECT_TYPE(object)); +} +#endif diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c new file mode 100644 index 000000000000..6e6c73cc39ff --- /dev/null +++ b/drivers/acpi/acpica/dsobject.c @@ -0,0 +1,813 @@ +/****************************************************************************** + * + * Module Name: dsobject - Dispatcher object management routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dsobject") + +/* Local prototypes */ +static acpi_status +acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, + union acpi_operand_object **obj_desc_ptr); + +#ifndef ACPI_NO_METHOD_EXECUTION +/******************************************************************************* + * + * FUNCTION: acpi_ds_build_internal_object + * + * PARAMETERS: walk_state - Current walk state + * Op - Parser object to be translated + * obj_desc_ptr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op object to the equivalent namespace object + * Simple objects are any objects other than a package object! + * + ******************************************************************************/ + +static acpi_status +acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, + union acpi_operand_object **obj_desc_ptr) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(ds_build_internal_object); + + *obj_desc_ptr = NULL; + if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { + /* + * This is a named object reference. If this name was + * previously looked up in the namespace, it was stored in this op. + * Otherwise, go ahead and look it up now + */ + if (!op->common.node) { + status = acpi_ns_lookup(walk_state->scope_info, + op->common.value.string, + ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | + ACPI_NS_DONT_OPEN_SCOPE, NULL, + ACPI_CAST_INDIRECT_PTR(struct + acpi_namespace_node, + &(op-> + common. + node))); + if (ACPI_FAILURE(status)) { + + /* Check if we are resolving a named reference within a package */ + + if ((status == AE_NOT_FOUND) + && (acpi_gbl_enable_interpreter_slack) + && + ((op->common.parent->common.aml_opcode == + AML_PACKAGE_OP) + || (op->common.parent->common.aml_opcode == + AML_VAR_PACKAGE_OP))) { + /* + * We didn't find the target and we are populating elements + * of a package - ignore if slack enabled. Some ASL code + * contains dangling invalid references in packages and + * expects that no exception will be issued. Leave the + * element as a null element. It cannot be used, but it + * can be overwritten by subsequent ASL code - this is + * typically the case. + */ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Ignoring unresolved reference in package [%4.4s]\n", + walk_state-> + scope_info->scope. + node->name.ascii)); + + return_ACPI_STATUS(AE_OK); + } else { + ACPI_ERROR_NAMESPACE(op->common.value. + string, status); + } + + return_ACPI_STATUS(status); + } + } + + /* Special object resolution for elements of a package */ + + if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == + AML_VAR_PACKAGE_OP)) { + /* + * Attempt to resolve the node to a value before we insert it into + * the package. If this is a reference to a common data type, + * resolve it immediately. According to the ACPI spec, package + * elements can only be "data objects" or method references. + * Attempt to resolve to an Integer, Buffer, String or Package. + * If cannot, return the named reference (for things like Devices, + * Methods, etc.) Buffer Fields and Fields will resolve to simple + * objects (int/buf/str/pkg). + * + * NOTE: References to things like Devices, Methods, Mutexes, etc. + * will remain as named references. This behavior is not described + * in the ACPI spec, but it appears to be an oversight. + */ + obj_desc = + ACPI_CAST_PTR(union acpi_operand_object, + op->common.node); + + status = + acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR + (struct + acpi_namespace_node, + &obj_desc), + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + switch (op->common.node->type) { + /* + * For these types, we need the actual node, not the subobject. + * However, the subobject did not get an extra reference count above. + * + * TBD: should ex_resolve_node_to_value be changed to fix this? + */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + acpi_ut_add_reference(op->common.node->object); + + /*lint -fallthrough */ + /* + * For these types, we need the actual node, not the subobject. + * The subobject got an extra reference count in ex_resolve_node_to_value. + */ + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_METHOD: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_REGION: + + /* We will create a reference object for these types below */ + break; + + default: + /* + * All other types - the node was resolved to an actual + * object, we are done. + */ + goto exit; + } + } + } + + /* Create and init a new internal ACPI object */ + + obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info + (op->common.aml_opcode))-> + object_type); + if (!obj_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + status = + acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode, + &obj_desc); + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); + } + + exit: + *obj_desc_ptr = obj_desc; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_build_internal_buffer_obj + * + * PARAMETERS: walk_state - Current walk state + * Op - Parser object to be translated + * buffer_length - Length of the buffer + * obj_desc_ptr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op package object to the equivalent + * namespace object + * + ******************************************************************************/ + +acpi_status +acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, + u32 buffer_length, + union acpi_operand_object **obj_desc_ptr) +{ + union acpi_parse_object *arg; + union acpi_operand_object *obj_desc; + union acpi_parse_object *byte_list; + u32 byte_list_length = 0; + + ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj); + + /* + * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". + * The buffer object already exists (from the NS node), otherwise it must + * be created. + */ + obj_desc = *obj_desc_ptr; + if (!obj_desc) { + + /* Create a new buffer object */ + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); + *obj_desc_ptr = obj_desc; + if (!obj_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + } + + /* + * Second arg is the buffer data (optional) byte_list can be either + * individual bytes or a string initializer. In either case, a + * byte_list appears in the AML. + */ + arg = op->common.value.arg; /* skip first arg */ + + byte_list = arg->named.next; + if (byte_list) { + if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) { + ACPI_ERROR((AE_INFO, + "Expecting bytelist, got AML opcode %X in op %p", + byte_list->common.aml_opcode, byte_list)); + + acpi_ut_remove_reference(obj_desc); + return (AE_TYPE); + } + + byte_list_length = (u32) byte_list->common.value.integer; + } + + /* + * The buffer length (number of bytes) will be the larger of: + * 1) The specified buffer length and + * 2) The length of the initializer byte list + */ + obj_desc->buffer.length = buffer_length; + if (byte_list_length > buffer_length) { + obj_desc->buffer.length = byte_list_length; + } + + /* Allocate the buffer */ + + if (obj_desc->buffer.length == 0) { + obj_desc->buffer.pointer = NULL; + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Buffer defined with zero length in AML, creating\n")); + } else { + obj_desc->buffer.pointer = + ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length); + if (!obj_desc->buffer.pointer) { + acpi_ut_delete_object_desc(obj_desc); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Initialize buffer from the byte_list (if present) */ + + if (byte_list) { + ACPI_MEMCPY(obj_desc->buffer.pointer, + byte_list->named.data, byte_list_length); + } + } + + obj_desc->buffer.flags |= AOPOBJ_DATA_VALID; + op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_build_internal_package_obj + * + * PARAMETERS: walk_state - Current walk state + * Op - Parser object to be translated + * element_count - Number of elements in the package - this is + * the num_elements argument to Package() + * obj_desc_ptr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op package object to the equivalent + * namespace object + * + * NOTE: The number of elements in the package will be always be the num_elements + * count, regardless of the number of elements in the package list. If + * num_elements is smaller, only that many package list elements are used. + * if num_elements is larger, the Package object is padded out with + * objects of type Uninitialized (as per ACPI spec.) + * + * Even though the ASL compilers do not allow num_elements to be smaller + * than the Package list length (for the fixed length package opcode), some + * BIOS code modifies the AML on the fly to adjust the num_elements, and + * this code compensates for that. This also provides compatibility with + * other AML interpreters. + * + ******************************************************************************/ + +acpi_status +acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, + u32 element_count, + union acpi_operand_object **obj_desc_ptr) +{ + union acpi_parse_object *arg; + union acpi_parse_object *parent; + union acpi_operand_object *obj_desc = NULL; + acpi_status status = AE_OK; + unsigned i; + u16 index; + u16 reference_count; + + ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); + + /* Find the parent of a possibly nested package */ + + parent = op->common.parent; + while ((parent->common.aml_opcode == AML_PACKAGE_OP) || + (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { + parent = parent->common.parent; + } + + /* + * If we are evaluating a Named package object "Name (xxxx, Package)", + * the package object already exists, otherwise it must be created. + */ + obj_desc = *obj_desc_ptr; + if (!obj_desc) { + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE); + *obj_desc_ptr = obj_desc; + if (!obj_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + obj_desc->package.node = parent->common.node; + } + + /* + * Allocate the element array (array of pointers to the individual + * objects) based on the num_elements parameter. Add an extra pointer slot + * so that the list is always null terminated. + */ + obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) + element_count + + 1) * sizeof(void *)); + + if (!obj_desc->package.elements) { + acpi_ut_delete_object_desc(obj_desc); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + obj_desc->package.count = element_count; + + /* + * Initialize the elements of the package, up to the num_elements count. + * Package is automatically padded with uninitialized (NULL) elements + * if num_elements is greater than the package list length. Likewise, + * Package is truncated if num_elements is less than the list length. + */ + arg = op->common.value.arg; + arg = arg->common.next; + for (i = 0; arg && (i < element_count); i++) { + if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { + if (arg->common.node->type == ACPI_TYPE_METHOD) { + /* + * A method reference "looks" to the parser to be a method + * invocation, so we special case it here + */ + arg->common.aml_opcode = AML_INT_NAMEPATH_OP; + status = + acpi_ds_build_internal_object(walk_state, + arg, + &obj_desc-> + package. + elements[i]); + } else { + /* This package element is already built, just get it */ + + obj_desc->package.elements[i] = + ACPI_CAST_PTR(union acpi_operand_object, + arg->common.node); + } + } else { + status = acpi_ds_build_internal_object(walk_state, arg, + &obj_desc-> + package. + elements[i]); + } + + if (*obj_desc_ptr) { + + /* Existing package, get existing reference count */ + + reference_count = + (*obj_desc_ptr)->common.reference_count; + if (reference_count > 1) { + + /* Make new element ref count match original ref count */ + + for (index = 0; index < (reference_count - 1); + index++) { + acpi_ut_add_reference((obj_desc-> + package. + elements[i])); + } + } + } + + arg = arg->common.next; + } + + /* Check for match between num_elements and actual length of package_list */ + + if (arg) { + /* + * num_elements was exhausted, but there are remaining elements in the + * package_list. + * + * Note: technically, this is an error, from ACPI spec: "It is an error + * for NumElements to be less than the number of elements in the + * PackageList". However, for now, we just print an error message and + * no exception is returned. + */ + while (arg) { + + /* Find out how many elements there really are */ + + i++; + arg = arg->common.next; + } + + ACPI_WARNING((AE_INFO, + "Package List length (%X) larger than NumElements count (%X), truncated\n", + i, element_count)); + } else if (i < element_count) { + /* + * Arg list (elements) was exhausted, but we did not reach num_elements count. + * Note: this is not an error, the package is padded out with NULLs. + */ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Package List length (%X) smaller than NumElements count (%X), padded with null elements\n", + i, element_count)); + } + + obj_desc->package.flags |= AOPOBJ_DATA_VALID; + op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_create_node + * + * PARAMETERS: walk_state - Current walk state + * Node - NS Node to be initialized + * Op - Parser object to be translated + * + * RETURN: Status + * + * DESCRIPTION: Create the object to be associated with a namespace node + * + ******************************************************************************/ + +acpi_status +acpi_ds_create_node(struct acpi_walk_state *walk_state, + struct acpi_namespace_node *node, + union acpi_parse_object *op) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + + ACPI_FUNCTION_TRACE_PTR(ds_create_node, op); + + /* + * Because of the execution pass through the non-control-method + * parts of the table, we can arrive here twice. Only init + * the named object node the first time through + */ + if (acpi_ns_get_attached_object(node)) { + return_ACPI_STATUS(AE_OK); + } + + if (!op->common.value.arg) { + + /* No arguments, there is nothing to do */ + + return_ACPI_STATUS(AE_OK); + } + + /* Build an internal object for the argument(s) */ + + status = acpi_ds_build_internal_object(walk_state, op->common.value.arg, + &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Re-type the object according to its argument */ + + node->type = ACPI_GET_OBJECT_TYPE(obj_desc); + + /* Attach obj to node */ + + status = acpi_ns_attach_object(node, obj_desc, node->type); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +#endif /* ACPI_NO_METHOD_EXECUTION */ + +/******************************************************************************* + * + * FUNCTION: acpi_ds_init_object_from_op + * + * PARAMETERS: walk_state - Current walk state + * Op - Parser op used to init the internal object + * Opcode - AML opcode associated with the object + * ret_obj_desc - Namespace object to be initialized + * + * RETURN: Status + * + * DESCRIPTION: Initialize a namespace object from a parser Op and its + * associated arguments. The namespace object is a more compact + * representation of the Op and its arguments. + * + ******************************************************************************/ + +acpi_status +acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, + u16 opcode, + union acpi_operand_object **ret_obj_desc) +{ + const struct acpi_opcode_info *op_info; + union acpi_operand_object *obj_desc; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ds_init_object_from_op); + + obj_desc = *ret_obj_desc; + op_info = acpi_ps_get_opcode_info(opcode); + if (op_info->class == AML_CLASS_UNKNOWN) { + + /* Unknown opcode */ + + return_ACPI_STATUS(AE_TYPE); + } + + /* Perform per-object initialization */ + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_BUFFER: + + /* + * Defer evaluation of Buffer term_arg operand + */ + obj_desc->buffer.node = + ACPI_CAST_PTR(struct acpi_namespace_node, + walk_state->operands[0]); + obj_desc->buffer.aml_start = op->named.data; + obj_desc->buffer.aml_length = op->named.length; + break; + + case ACPI_TYPE_PACKAGE: + + /* + * Defer evaluation of Package term_arg operand + */ + obj_desc->package.node = + ACPI_CAST_PTR(struct acpi_namespace_node, + walk_state->operands[0]); + obj_desc->package.aml_start = op->named.data; + obj_desc->package.aml_length = op->named.length; + break; + + case ACPI_TYPE_INTEGER: + + switch (op_info->type) { + case AML_TYPE_CONSTANT: + /* + * Resolve AML Constants here - AND ONLY HERE! + * All constants are integers. + * We mark the integer with a flag that indicates that it started + * life as a constant -- so that stores to constants will perform + * as expected (noop). zero_op is used as a placeholder for optional + * target operands. + */ + obj_desc->common.flags = AOPOBJ_AML_CONSTANT; + + switch (opcode) { + case AML_ZERO_OP: + + obj_desc->integer.value = 0; + break; + + case AML_ONE_OP: + + obj_desc->integer.value = 1; + break; + + case AML_ONES_OP: + + obj_desc->integer.value = ACPI_INTEGER_MAX; + + /* Truncate value if we are executing from a 32-bit ACPI table */ + +#ifndef ACPI_NO_METHOD_EXECUTION + acpi_ex_truncate_for32bit_table(obj_desc); +#endif + break; + + case AML_REVISION_OP: + + obj_desc->integer.value = ACPI_CA_VERSION; + break; + + default: + + ACPI_ERROR((AE_INFO, + "Unknown constant opcode %X", + opcode)); + status = AE_AML_OPERAND_TYPE; + break; + } + break; + + case AML_TYPE_LITERAL: + + obj_desc->integer.value = op->common.value.integer; +#ifndef ACPI_NO_METHOD_EXECUTION + acpi_ex_truncate_for32bit_table(obj_desc); +#endif + break; + + default: + ACPI_ERROR((AE_INFO, "Unknown Integer type %X", + op_info->type)); + status = AE_AML_OPERAND_TYPE; + break; + } + break; + + case ACPI_TYPE_STRING: + + obj_desc->string.pointer = op->common.value.string; + obj_desc->string.length = + (u32) ACPI_STRLEN(op->common.value.string); + + /* + * The string is contained in the ACPI table, don't ever try + * to delete it + */ + obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; + break; + + case ACPI_TYPE_METHOD: + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + switch (op_info->type) { + case AML_TYPE_LOCAL_VARIABLE: + + /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */ + + obj_desc->reference.value = opcode - AML_LOCAL_OP; + obj_desc->reference.class = ACPI_REFCLASS_LOCAL; + +#ifndef ACPI_NO_METHOD_EXECUTION + status = + acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL, + obj_desc->reference. + value, walk_state, + ACPI_CAST_INDIRECT_PTR + (struct + acpi_namespace_node, + &obj_desc->reference. + object)); +#endif + break; + + case AML_TYPE_METHOD_ARGUMENT: + + /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */ + + obj_desc->reference.value = opcode - AML_ARG_OP; + obj_desc->reference.class = ACPI_REFCLASS_ARG; + +#ifndef ACPI_NO_METHOD_EXECUTION + status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG, + obj_desc-> + reference.value, + walk_state, + ACPI_CAST_INDIRECT_PTR + (struct + acpi_namespace_node, + &obj_desc-> + reference. + object)); +#endif + break; + + default: /* Object name or Debug object */ + + switch (op->common.aml_opcode) { + case AML_INT_NAMEPATH_OP: + + /* Node was saved in Op */ + + obj_desc->reference.node = op->common.node; + obj_desc->reference.object = + op->common.node->object; + obj_desc->reference.class = ACPI_REFCLASS_NAME; + break; + + case AML_DEBUG_OP: + + obj_desc->reference.class = ACPI_REFCLASS_DEBUG; + break; + + default: + + ACPI_ERROR((AE_INFO, + "Unimplemented reference type for AML opcode: %4.4X", + opcode)); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + break; + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Unimplemented data type: %X", + ACPI_GET_OBJECT_TYPE(obj_desc))); + + status = AE_AML_OPERAND_TYPE; + break; + } + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c new file mode 100644 index 000000000000..cb8a0d3109f0 --- /dev/null +++ b/drivers/acpi/acpica/dsopcode.c @@ -0,0 +1,1469 @@ +/****************************************************************************** + * + * Module Name: dsopcode - Dispatcher Op Region support and handling of + * "control" opcodes + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dsopcode") + +/* Local prototypes */ +static acpi_status +acpi_ds_execute_arguments(struct acpi_namespace_node *node, + struct acpi_namespace_node *scope_node, + u32 aml_length, u8 * aml_start); + +static acpi_status +acpi_ds_init_buffer_field(u16 aml_opcode, + union acpi_operand_object *obj_desc, + union acpi_operand_object *buffer_desc, + union acpi_operand_object *offset_desc, + union acpi_operand_object *length_desc, + union acpi_operand_object *result_desc); + +/******************************************************************************* + * + * FUNCTION: acpi_ds_execute_arguments + * + * PARAMETERS: Node - Object NS node + * scope_node - Parent NS node + * aml_length - Length of executable AML + * aml_start - Pointer to the AML + * + * RETURN: Status. + * + * DESCRIPTION: Late (deferred) execution of region or field arguments + * + ******************************************************************************/ + +static acpi_status +acpi_ds_execute_arguments(struct acpi_namespace_node *node, + struct acpi_namespace_node *scope_node, + u32 aml_length, u8 * aml_start) +{ + acpi_status status; + union acpi_parse_object *op; + struct acpi_walk_state *walk_state; + + ACPI_FUNCTION_TRACE(ds_execute_arguments); + + /* + * Allocate a new parser op to be the root of the parsed tree + */ + op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Save the Node for use in acpi_ps_parse_aml */ + + op->common.node = scope_node; + + /* Create and initialize a new parser state */ + + walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); + if (!walk_state) { + status = AE_NO_MEMORY; + goto cleanup; + } + + status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, + aml_length, NULL, ACPI_IMODE_LOAD_PASS1); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } + + /* Mark this parse as a deferred opcode */ + + walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; + walk_state->deferred_node = node; + + /* Pass1: Parse the entire declaration */ + + status = acpi_ps_parse_aml(walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Get and init the Op created above */ + + op->common.node = node; + acpi_ps_delete_parse_tree(op); + + /* Evaluate the deferred arguments */ + + op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + op->common.node = scope_node; + + /* Create and initialize a new parser state */ + + walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); + if (!walk_state) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Execute the opcode and arguments */ + + status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, + aml_length, NULL, ACPI_IMODE_EXECUTE); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } + + /* Mark this execution as a deferred opcode */ + + walk_state->deferred_node = node; + status = acpi_ps_parse_aml(walk_state); + + cleanup: + acpi_ps_delete_parse_tree(op); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_buffer_field_arguments + * + * PARAMETERS: obj_desc - A valid buffer_field object + * + * RETURN: Status. + * + * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late + * evaluation of these field attributes. + * + ******************************************************************************/ + +acpi_status +acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) +{ + union acpi_operand_object *extra_desc; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the AML pointer (method object) and buffer_field node */ + + extra_desc = acpi_ns_get_secondary_object(obj_desc); + node = obj_desc->buffer_field.node; + + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_BUFFER_FIELD, node, NULL)); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", + acpi_ut_get_node_name(node))); + + /* Execute the AML code for the term_arg arguments */ + + status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), + extra_desc->extra.aml_length, + extra_desc->extra.aml_start); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_bank_field_arguments + * + * PARAMETERS: obj_desc - A valid bank_field object + * + * RETURN: Status. + * + * DESCRIPTION: Get bank_field bank_value. This implements the late + * evaluation of these field attributes. + * + ******************************************************************************/ + +acpi_status +acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) +{ + union acpi_operand_object *extra_desc; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the AML pointer (method object) and bank_field node */ + + extra_desc = acpi_ns_get_secondary_object(obj_desc); + node = obj_desc->bank_field.node; + + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", + acpi_ut_get_node_name(node))); + + /* Execute the AML code for the term_arg arguments */ + + status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), + extra_desc->extra.aml_length, + extra_desc->extra.aml_start); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_buffer_arguments + * + * PARAMETERS: obj_desc - A valid Buffer object + * + * RETURN: Status. + * + * DESCRIPTION: Get Buffer length and initializer byte list. This implements + * the late evaluation of these attributes. + * + ******************************************************************************/ + +acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) +{ + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the Buffer node */ + + node = obj_desc->buffer.node; + if (!node) { + ACPI_ERROR((AE_INFO, + "No pointer back to NS node in buffer obj %p", + obj_desc)); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); + + /* Execute the AML code for the term_arg arguments */ + + status = acpi_ds_execute_arguments(node, node, + obj_desc->buffer.aml_length, + obj_desc->buffer.aml_start); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_package_arguments + * + * PARAMETERS: obj_desc - A valid Package object + * + * RETURN: Status. + * + * DESCRIPTION: Get Package length and initializer byte list. This implements + * the late evaluation of these attributes. + * + ******************************************************************************/ + +acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) +{ + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the Package node */ + + node = obj_desc->package.node; + if (!node) { + ACPI_ERROR((AE_INFO, + "No pointer back to NS node in package %p", + obj_desc)); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); + + /* Execute the AML code for the term_arg arguments */ + + status = acpi_ds_execute_arguments(node, node, + obj_desc->package.aml_length, + obj_desc->package.aml_start); + return_ACPI_STATUS(status); +} + +/***************************************************************************** + * + * FUNCTION: acpi_ds_get_region_arguments + * + * PARAMETERS: obj_desc - A valid region object + * + * RETURN: Status. + * + * DESCRIPTION: Get region address and length. This implements the late + * evaluation of these region attributes. + * + ****************************************************************************/ + +acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) +{ + struct acpi_namespace_node *node; + acpi_status status; + union acpi_operand_object *extra_desc; + + ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); + + if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { + return_ACPI_STATUS(AE_OK); + } + + extra_desc = acpi_ns_get_secondary_object(obj_desc); + if (!extra_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Get the Region node */ + + node = obj_desc->region.node; + + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_REGION, node, NULL)); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", + acpi_ut_get_node_name(node), + extra_desc->extra.aml_start)); + + /* Execute the argument AML */ + + status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), + extra_desc->extra.aml_length, + extra_desc->extra.aml_start); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Validate the region address/length via the host OS */ + + status = acpi_os_validate_address(obj_desc->region.space_id, + obj_desc->region.address, + (acpi_size) obj_desc->region.length, + acpi_ut_get_node_name(node)); + + if (ACPI_FAILURE(status)) { + /* + * Invalid address/length. We will emit an error message and mark + * the region as invalid, so that it will cause an additional error if + * it is ever used. Then return AE_OK. + */ + ACPI_EXCEPTION((AE_INFO, status, + "During address validation of OpRegion [%4.4s]", + node->name.ascii)); + obj_desc->common.flags |= AOPOBJ_INVALID; + status = AE_OK; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_initialize_region + * + * PARAMETERS: obj_handle - Region namespace node + * + * RETURN: Status + * + * DESCRIPTION: Front end to ev_initialize_region + * + ******************************************************************************/ + +acpi_status acpi_ds_initialize_region(acpi_handle obj_handle) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + obj_desc = acpi_ns_get_attached_object(obj_handle); + + /* Namespace is NOT locked */ + + status = acpi_ev_initialize_region(obj_desc, FALSE); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_init_buffer_field + * + * PARAMETERS: aml_opcode - create_xxx_field + * obj_desc - buffer_field object + * buffer_desc - Host Buffer + * offset_desc - Offset into buffer + * length_desc - Length of field (CREATE_FIELD_OP only) + * result_desc - Where to store the result + * + * RETURN: Status + * + * DESCRIPTION: Perform actual initialization of a buffer field + * + ******************************************************************************/ + +static acpi_status +acpi_ds_init_buffer_field(u16 aml_opcode, + union acpi_operand_object *obj_desc, + union acpi_operand_object *buffer_desc, + union acpi_operand_object *offset_desc, + union acpi_operand_object *length_desc, + union acpi_operand_object *result_desc) +{ + u32 offset; + u32 bit_offset; + u32 bit_count; + u8 field_flags; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc); + + /* Host object must be a Buffer */ + + if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) { + ACPI_ERROR((AE_INFO, + "Target of Create Field is not a Buffer object - %s", + acpi_ut_get_object_type_name(buffer_desc))); + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + /* + * The last parameter to all of these opcodes (result_desc) started + * out as a name_string, and should therefore now be a NS node + * after resolution in acpi_ex_resolve_operands(). + */ + if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) { + ACPI_ERROR((AE_INFO, + "(%s) destination not a NS Node [%s]", + acpi_ps_get_opcode_name(aml_opcode), + acpi_ut_get_descriptor_name(result_desc))); + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + offset = (u32) offset_desc->integer.value; + + /* + * Setup the Bit offsets and counts, according to the opcode + */ + switch (aml_opcode) { + case AML_CREATE_FIELD_OP: + + /* Offset is in bits, count is in bits */ + + field_flags = AML_FIELD_ACCESS_BYTE; + bit_offset = offset; + bit_count = (u32) length_desc->integer.value; + + /* Must have a valid (>0) bit count */ + + if (bit_count == 0) { + ACPI_ERROR((AE_INFO, + "Attempt to CreateField of length zero")); + status = AE_AML_OPERAND_VALUE; + goto cleanup; + } + break; + + case AML_CREATE_BIT_FIELD_OP: + + /* Offset is in bits, Field is one bit */ + + bit_offset = offset; + bit_count = 1; + field_flags = AML_FIELD_ACCESS_BYTE; + break; + + case AML_CREATE_BYTE_FIELD_OP: + + /* Offset is in bytes, field is one byte */ + + bit_offset = 8 * offset; + bit_count = 8; + field_flags = AML_FIELD_ACCESS_BYTE; + break; + + case AML_CREATE_WORD_FIELD_OP: + + /* Offset is in bytes, field is one word */ + + bit_offset = 8 * offset; + bit_count = 16; + field_flags = AML_FIELD_ACCESS_WORD; + break; + + case AML_CREATE_DWORD_FIELD_OP: + + /* Offset is in bytes, field is one dword */ + + bit_offset = 8 * offset; + bit_count = 32; + field_flags = AML_FIELD_ACCESS_DWORD; + break; + + case AML_CREATE_QWORD_FIELD_OP: + + /* Offset is in bytes, field is one qword */ + + bit_offset = 8 * offset; + bit_count = 64; + field_flags = AML_FIELD_ACCESS_QWORD; + break; + + default: + + ACPI_ERROR((AE_INFO, + "Unknown field creation opcode %02x", aml_opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + /* Entire field must fit within the current length of the buffer */ + + if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) { + ACPI_ERROR((AE_INFO, + "Field [%4.4s] at %d exceeds Buffer [%4.4s] size %d (bits)", + acpi_ut_get_node_name(result_desc), + bit_offset + bit_count, + acpi_ut_get_node_name(buffer_desc->buffer.node), + 8 * (u32) buffer_desc->buffer.length)); + status = AE_AML_BUFFER_LIMIT; + goto cleanup; + } + + /* + * Initialize areas of the field object that are common to all fields + * For field_flags, use LOCK_RULE = 0 (NO_LOCK), + * UPDATE_RULE = 0 (UPDATE_PRESERVE) + */ + status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0, + bit_offset, bit_count); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + obj_desc->buffer_field.buffer_obj = buffer_desc; + + /* Reference count for buffer_desc inherits obj_desc count */ + + buffer_desc->common.reference_count = (u16) + (buffer_desc->common.reference_count + + obj_desc->common.reference_count); + + cleanup: + + /* Always delete the operands */ + + acpi_ut_remove_reference(offset_desc); + acpi_ut_remove_reference(buffer_desc); + + if (aml_opcode == AML_CREATE_FIELD_OP) { + acpi_ut_remove_reference(length_desc); + } + + /* On failure, delete the result descriptor */ + + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(result_desc); /* Result descriptor */ + } else { + /* Now the address and length are valid for this buffer_field */ + + obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_eval_buffer_field_operands + * + * PARAMETERS: walk_state - Current walk + * Op - A valid buffer_field Op object + * + * RETURN: Status + * + * DESCRIPTION: Get buffer_field Buffer and Index + * Called from acpi_ds_exec_end_op during buffer_field parse tree walk + * + ******************************************************************************/ + +acpi_status +acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + union acpi_parse_object *next_op; + + ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op); + + /* + * This is where we evaluate the address and length fields of the + * create_xxx_field declaration + */ + node = op->common.node; + + /* next_op points to the op that holds the Buffer */ + + next_op = op->common.value.arg; + + /* Evaluate/create the address and length operands */ + + status = acpi_ds_create_operands(walk_state, next_op); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Resolve the operands */ + + status = acpi_ex_resolve_operands(op->common.aml_opcode, + ACPI_WALK_OPERANDS, walk_state); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)", + acpi_ps_get_opcode_name(op->common.aml_opcode), + status)); + + return_ACPI_STATUS(status); + } + + /* Initialize the Buffer Field */ + + if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { + + /* NOTE: Slightly different operands for this opcode */ + + status = + acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, + walk_state->operands[0], + walk_state->operands[1], + walk_state->operands[2], + walk_state->operands[3]); + } else { + /* All other, create_xxx_field opcodes */ + + status = + acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, + walk_state->operands[0], + walk_state->operands[1], NULL, + walk_state->operands[2]); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_eval_region_operands + * + * PARAMETERS: walk_state - Current walk + * Op - A valid region Op object + * + * RETURN: Status + * + * DESCRIPTION: Get region address and length + * Called from acpi_ds_exec_end_op during op_region parse tree walk + * + ******************************************************************************/ + +acpi_status +acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + union acpi_operand_object *operand_desc; + struct acpi_namespace_node *node; + union acpi_parse_object *next_op; + + ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op); + + /* + * This is where we evaluate the address and length fields of the + * op_region declaration + */ + node = op->common.node; + + /* next_op points to the op that holds the space_iD */ + + next_op = op->common.value.arg; + + /* next_op points to address op */ + + next_op = next_op->common.next; + + /* Evaluate/create the address and length operands */ + + status = acpi_ds_create_operands(walk_state, next_op); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Resolve the length and address operands to numbers */ + + status = acpi_ex_resolve_operands(op->common.aml_opcode, + ACPI_WALK_OPERANDS, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* + * Get the length operand and save it + * (at Top of stack) + */ + operand_desc = walk_state->operands[walk_state->num_operands - 1]; + + obj_desc->region.length = (u32) operand_desc->integer.value; + acpi_ut_remove_reference(operand_desc); + + /* + * Get the address and save it + * (at top of stack - 1) + */ + operand_desc = walk_state->operands[walk_state->num_operands - 2]; + + obj_desc->region.address = (acpi_physical_address) + operand_desc->integer.value; + acpi_ut_remove_reference(operand_desc); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + obj_desc, + ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), + obj_desc->region.length)); + + /* Now the address and length are valid for this opregion */ + + obj_desc->region.flags |= AOPOBJ_DATA_VALID; + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_eval_table_region_operands + * + * PARAMETERS: walk_state - Current walk + * Op - A valid region Op object + * + * RETURN: Status + * + * DESCRIPTION: Get region address and length + * Called from acpi_ds_exec_end_op during data_table_region parse tree walk + * + ******************************************************************************/ + +acpi_status +acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + union acpi_operand_object **operand; + struct acpi_namespace_node *node; + union acpi_parse_object *next_op; + u32 table_index; + struct acpi_table_header *table; + + ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); + + /* + * This is where we evaluate the signature_string and oem_iDString + * and oem_table_iDString of the data_table_region declaration + */ + node = op->common.node; + + /* next_op points to signature_string op */ + + next_op = op->common.value.arg; + + /* + * Evaluate/create the signature_string and oem_iDString + * and oem_table_iDString operands + */ + status = acpi_ds_create_operands(walk_state, next_op); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Resolve the signature_string and oem_iDString + * and oem_table_iDString operands + */ + status = acpi_ex_resolve_operands(op->common.aml_opcode, + ACPI_WALK_OPERANDS, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + operand = &walk_state->operands[0]; + + /* Find the ACPI table */ + + status = acpi_tb_find_table(operand[0]->string.pointer, + operand[1]->string.pointer, + operand[2]->string.pointer, &table_index); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ut_remove_reference(operand[0]); + acpi_ut_remove_reference(operand[1]); + acpi_ut_remove_reference(operand[2]); + + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + obj_desc->region.address = + (acpi_physical_address) ACPI_TO_INTEGER(table); + obj_desc->region.length = table->length; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + obj_desc, + ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), + obj_desc->region.length)); + + /* Now the address and length are valid for this opregion */ + + obj_desc->region.flags |= AOPOBJ_DATA_VALID; + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_eval_data_object_operands + * + * PARAMETERS: walk_state - Current walk + * Op - A valid data_object Op object + * obj_desc - data_object + * + * RETURN: Status + * + * DESCRIPTION: Get the operands and complete the following data object types: + * Buffer, Package. + * + ******************************************************************************/ + +acpi_status +acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, + union acpi_operand_object *obj_desc) +{ + acpi_status status; + union acpi_operand_object *arg_desc; + u32 length; + + ACPI_FUNCTION_TRACE(ds_eval_data_object_operands); + + /* The first operand (for all of these data objects) is the length */ + + /* + * Set proper index into operand stack for acpi_ds_obj_stack_push + * invoked inside acpi_ds_create_operand. + */ + walk_state->operand_index = walk_state->num_operands; + + status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_ex_resolve_operands(walk_state->opcode, + &(walk_state-> + operands[walk_state->num_operands - + 1]), walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Extract length operand */ + + arg_desc = walk_state->operands[walk_state->num_operands - 1]; + length = (u32) arg_desc->integer.value; + + /* Cleanup for length operand */ + + status = acpi_ds_obj_stack_pop(1, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ut_remove_reference(arg_desc); + + /* + * Create the actual data object + */ + switch (op->common.aml_opcode) { + case AML_BUFFER_OP: + + status = + acpi_ds_build_internal_buffer_obj(walk_state, op, length, + &obj_desc); + break; + + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + status = + acpi_ds_build_internal_package_obj(walk_state, op, length, + &obj_desc); + break; + + default: + return_ACPI_STATUS(AE_AML_BAD_OPCODE); + } + + if (ACPI_SUCCESS(status)) { + /* + * Return the object in the walk_state, unless the parent is a package - + * in this case, the return object will be stored in the parse tree + * for the package. + */ + if ((!op->common.parent) || + ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && + (op->common.parent->common.aml_opcode != + AML_VAR_PACKAGE_OP) + && (op->common.parent->common.aml_opcode != AML_NAME_OP))) { + walk_state->result_obj = obj_desc; + } + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_eval_bank_field_operands + * + * PARAMETERS: walk_state - Current walk + * Op - A valid bank_field Op object + * + * RETURN: Status + * + * DESCRIPTION: Get bank_field bank_value + * Called from acpi_ds_exec_end_op during bank_field parse tree walk + * + ******************************************************************************/ + +acpi_status +acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + union acpi_operand_object *operand_desc; + struct acpi_namespace_node *node; + union acpi_parse_object *next_op; + union acpi_parse_object *arg; + + ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); + + /* + * This is where we evaluate the bank_value field of the + * bank_field declaration + */ + + /* next_op points to the op that holds the Region */ + + next_op = op->common.value.arg; + + /* next_op points to the op that holds the Bank Register */ + + next_op = next_op->common.next; + + /* next_op points to the op that holds the Bank Value */ + + next_op = next_op->common.next; + + /* + * Set proper index into operand stack for acpi_ds_obj_stack_push + * invoked inside acpi_ds_create_operand. + * + * We use walk_state->Operands[0] to store the evaluated bank_value + */ + walk_state->operand_index = 0; + + status = acpi_ds_create_operand(walk_state, next_op, 0); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, + acpi_ps_get_opcode_name(op->common.aml_opcode), 1); + /* + * Get the bank_value operand and save it + * (at Top of stack) + */ + operand_desc = walk_state->operands[0]; + + /* Arg points to the start Bank Field */ + + arg = acpi_ps_get_arg(op, 4); + while (arg) { + + /* Ignore OFFSET and ACCESSAS terms here */ + + if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { + node = arg->common.node; + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + obj_desc->bank_field.value = + (u32) operand_desc->integer.value; + } + + /* Move to next field in the list */ + + arg = arg->common.next; + } + + acpi_ut_remove_reference(operand_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_exec_begin_control_op + * + * PARAMETERS: walk_list - The list that owns the walk stack + * Op - The control Op + * + * RETURN: Status + * + * DESCRIPTION: Handles all control ops encountered during control method + * execution. + * + ******************************************************************************/ + +acpi_status +acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + acpi_status status = AE_OK; + union acpi_generic_state *control_state; + + ACPI_FUNCTION_NAME(ds_exec_begin_control_op); + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, + op->common.aml_opcode, walk_state)); + + switch (op->common.aml_opcode) { + case AML_WHILE_OP: + + /* + * If this is an additional iteration of a while loop, continue. + * There is no need to allocate a new control state. + */ + if (walk_state->control_state) { + if (walk_state->control_state->control.aml_predicate_start + == (walk_state->parser_state.aml - 1)) { + + /* Reset the state to start-of-loop */ + + walk_state->control_state->common.state = + ACPI_CONTROL_CONDITIONAL_EXECUTING; + break; + } + } + + /*lint -fallthrough */ + + case AML_IF_OP: + + /* + * IF/WHILE: Create a new control state to manage these + * constructs. We need to manage these as a stack, in order + * to handle nesting. + */ + control_state = acpi_ut_create_control_state(); + if (!control_state) { + status = AE_NO_MEMORY; + break; + } + /* + * Save a pointer to the predicate for multiple executions + * of a loop + */ + control_state->control.aml_predicate_start = + walk_state->parser_state.aml - 1; + control_state->control.package_end = + walk_state->parser_state.pkg_end; + control_state->control.opcode = op->common.aml_opcode; + + /* Push the control state on this walk's control stack */ + + acpi_ut_push_generic_state(&walk_state->control_state, + control_state); + break; + + case AML_ELSE_OP: + + /* Predicate is in the state object */ + /* If predicate is true, the IF was executed, ignore ELSE part */ + + if (walk_state->last_predicate) { + status = AE_CTRL_TRUE; + } + + break; + + case AML_RETURN_OP: + + break; + + default: + break; + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_exec_end_control_op + * + * PARAMETERS: walk_list - The list that owns the walk stack + * Op - The control Op + * + * RETURN: Status + * + * DESCRIPTION: Handles all control ops encountered during control method + * execution. + * + ******************************************************************************/ + +acpi_status +acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, + union acpi_parse_object * op) +{ + acpi_status status = AE_OK; + union acpi_generic_state *control_state; + + ACPI_FUNCTION_NAME(ds_exec_end_control_op); + + switch (op->common.aml_opcode) { + case AML_IF_OP: + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); + + /* + * Save the result of the predicate in case there is an + * ELSE to come + */ + walk_state->last_predicate = + (u8) walk_state->control_state->common.value; + + /* + * Pop the control state that was created at the start + * of the IF and free it + */ + control_state = + acpi_ut_pop_generic_state(&walk_state->control_state); + acpi_ut_delete_generic_state(control_state); + break; + + case AML_ELSE_OP: + + break; + + case AML_WHILE_OP: + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); + + control_state = walk_state->control_state; + if (control_state->common.value) { + + /* Predicate was true, the body of the loop was just executed */ + + /* + * This loop counter mechanism allows the interpreter to escape + * possibly infinite loops. This can occur in poorly written AML + * when the hardware does not respond within a while loop and the + * loop does not implement a timeout. + */ + control_state->control.loop_count++; + if (control_state->control.loop_count > + ACPI_MAX_LOOP_ITERATIONS) { + status = AE_AML_INFINITE_LOOP; + break; + } + + /* + * Go back and evaluate the predicate and maybe execute the loop + * another time + */ + status = AE_CTRL_PENDING; + walk_state->aml_last_while = + control_state->control.aml_predicate_start; + break; + } + + /* Predicate was false, terminate this while loop */ + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "[WHILE_OP] termination! Op=%p\n", op)); + + /* Pop this control state and free it */ + + control_state = + acpi_ut_pop_generic_state(&walk_state->control_state); + acpi_ut_delete_generic_state(control_state); + break; + + case AML_RETURN_OP: + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "[RETURN_OP] Op=%p Arg=%p\n", op, + op->common.value.arg)); + + /* + * One optional operand -- the return value + * It can be either an immediate operand or a result that + * has been bubbled up the tree + */ + if (op->common.value.arg) { + + /* Since we have a real Return(), delete any implicit return */ + + acpi_ds_clear_implicit_return(walk_state); + + /* Return statement has an immediate operand */ + + status = + acpi_ds_create_operands(walk_state, + op->common.value.arg); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * If value being returned is a Reference (such as + * an arg or local), resolve it now because it may + * cease to exist at the end of the method. + */ + status = + acpi_ex_resolve_to_value(&walk_state->operands[0], + walk_state); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Get the return value and save as the last result + * value. This is the only place where walk_state->return_desc + * is set to anything other than zero! + */ + walk_state->return_desc = walk_state->operands[0]; + } else if (walk_state->result_count) { + + /* Since we have a real Return(), delete any implicit return */ + + acpi_ds_clear_implicit_return(walk_state); + + /* + * The return value has come from a previous calculation. + * + * If value being returned is a Reference (such as + * an arg or local), resolve it now because it may + * cease to exist at the end of the method. + * + * Allow references created by the Index operator to return unchanged. + */ + if ((ACPI_GET_DESCRIPTOR_TYPE + (walk_state->results->results.obj_desc[0]) == + ACPI_DESC_TYPE_OPERAND) + && + (ACPI_GET_OBJECT_TYPE + (walk_state->results->results.obj_desc[0]) == + ACPI_TYPE_LOCAL_REFERENCE) + && ((walk_state->results->results.obj_desc[0])-> + reference.class != ACPI_REFCLASS_INDEX)) { + status = + acpi_ex_resolve_to_value(&walk_state-> + results->results. + obj_desc[0], + walk_state); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + walk_state->return_desc = + walk_state->results->results.obj_desc[0]; + } else { + /* No return operand */ + + if (walk_state->num_operands) { + acpi_ut_remove_reference(walk_state-> + operands[0]); + } + + walk_state->operands[0] = NULL; + walk_state->num_operands = 0; + walk_state->return_desc = NULL; + } + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Completed RETURN_OP State=%p, RetVal=%p\n", + walk_state, walk_state->return_desc)); + + /* End the control method execution right now */ + + status = AE_CTRL_TERMINATE; + break; + + case AML_NOOP_OP: + + /* Just do nothing! */ + break; + + case AML_BREAK_POINT_OP: + + /* Call up to the OS service layer to handle this */ + + status = + acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, + "Executed AML Breakpoint opcode"); + + /* If and when it returns, all done. */ + + break; + + case AML_BREAK_OP: + case AML_CONTINUE_OP: /* ACPI 2.0 */ + + /* Pop and delete control states until we find a while */ + + while (walk_state->control_state && + (walk_state->control_state->control.opcode != + AML_WHILE_OP)) { + control_state = + acpi_ut_pop_generic_state(&walk_state-> + control_state); + acpi_ut_delete_generic_state(control_state); + } + + /* No while found? */ + + if (!walk_state->control_state) { + return (AE_AML_NO_WHILE); + } + + /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ + + walk_state->aml_last_while = + walk_state->control_state->control.package_end; + + /* Return status depending on opcode */ + + if (op->common.aml_opcode == AML_BREAK_OP) { + status = AE_CTRL_BREAK; + } else { + status = AE_CTRL_CONTINUE; + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p", + op->common.aml_opcode, op)); + + status = AE_AML_BAD_OPCODE; + break; + } + + return (status); +} diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c new file mode 100644 index 000000000000..9c88846ca2ce --- /dev/null +++ b/drivers/acpi/acpica/dsutils.c @@ -0,0 +1,869 @@ +/******************************************************************************* + * + * Module Name: dsutils - Dispatcher utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dsutils") + +/******************************************************************************* + * + * FUNCTION: acpi_ds_clear_implicit_return + * + * PARAMETERS: walk_state - Current State + * + * RETURN: None. + * + * DESCRIPTION: Clear and remove a reference on an implicit return value. Used + * to delete "stale" return values (if enabled, the return value + * from every operator is saved at least momentarily, in case the + * parent method exits.) + * + ******************************************************************************/ +void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state) +{ + ACPI_FUNCTION_NAME(ds_clear_implicit_return); + + /* + * Slack must be enabled for this feature + */ + if (!acpi_gbl_enable_interpreter_slack) { + return; + } + + if (walk_state->implicit_return_obj) { + /* + * Delete any "stale" implicit return. However, in + * complex statements, the implicit return value can be + * bubbled up several levels. + */ + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Removing reference on stale implicit return obj %p\n", + walk_state->implicit_return_obj)); + + acpi_ut_remove_reference(walk_state->implicit_return_obj); + walk_state->implicit_return_obj = NULL; + } +} + +#ifndef ACPI_NO_METHOD_EXECUTION +/******************************************************************************* + * + * FUNCTION: acpi_ds_do_implicit_return + * + * PARAMETERS: return_desc - The return value + * walk_state - Current State + * add_reference - True if a reference should be added to the + * return object + * + * RETURN: TRUE if implicit return enabled, FALSE otherwise + * + * DESCRIPTION: Implements the optional "implicit return". We save the result + * of every ASL operator and control method invocation in case the + * parent method exit. Before storing a new return value, we + * delete the previous return value. + * + ******************************************************************************/ + +u8 +acpi_ds_do_implicit_return(union acpi_operand_object *return_desc, + struct acpi_walk_state *walk_state, u8 add_reference) +{ + ACPI_FUNCTION_NAME(ds_do_implicit_return); + + /* + * Slack must be enabled for this feature, and we must + * have a valid return object + */ + if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) { + return (FALSE); + } + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Result %p will be implicitly returned; Prev=%p\n", + return_desc, walk_state->implicit_return_obj)); + + /* + * Delete any "stale" implicit return value first. However, in + * complex statements, the implicit return value can be + * bubbled up several levels, so we don't clear the value if it + * is the same as the return_desc. + */ + if (walk_state->implicit_return_obj) { + if (walk_state->implicit_return_obj == return_desc) { + return (TRUE); + } + acpi_ds_clear_implicit_return(walk_state); + } + + /* Save the implicit return value, add a reference if requested */ + + walk_state->implicit_return_obj = return_desc; + if (add_reference) { + acpi_ut_add_reference(return_desc); + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_is_result_used + * + * PARAMETERS: Op - Current Op + * walk_state - Current State + * + * RETURN: TRUE if result is used, FALSE otherwise + * + * DESCRIPTION: Check if a result object will be used by the parent + * + ******************************************************************************/ + +u8 +acpi_ds_is_result_used(union acpi_parse_object * op, + struct acpi_walk_state * walk_state) +{ + const struct acpi_opcode_info *parent_info; + + ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op); + + /* Must have both an Op and a Result Object */ + + if (!op) { + ACPI_ERROR((AE_INFO, "Null Op")); + return_UINT8(TRUE); + } + + /* + * We know that this operator is not a + * Return() operator (would not come here.) The following code is the + * optional support for a so-called "implicit return". Some AML code + * assumes that the last value of the method is "implicitly" returned + * to the caller. Just save the last result as the return value. + * NOTE: this is optional because the ASL language does not actually + * support this behavior. + */ + (void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state, + TRUE); + + /* + * Now determine if the parent will use the result + * + * If there is no parent, or the parent is a scope_op, we are executing + * at the method level. An executing method typically has no parent, + * since each method is parsed separately. A method invoked externally + * via execute_control_method has a scope_op as the parent. + */ + if ((!op->common.parent) || + (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) { + + /* No parent, the return value cannot possibly be used */ + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "At Method level, result of [%s] not used\n", + acpi_ps_get_opcode_name(op->common. + aml_opcode))); + return_UINT8(FALSE); + } + + /* Get info on the parent. The root_op is AML_SCOPE */ + + parent_info = + acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode); + if (parent_info->class == AML_CLASS_UNKNOWN) { + ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op)); + return_UINT8(FALSE); + } + + /* + * Decide what to do with the result based on the parent. If + * the parent opcode will not use the result, delete the object. + * Otherwise leave it as is, it will be deleted when it is used + * as an operand later. + */ + switch (parent_info->class) { + case AML_CLASS_CONTROL: + + switch (op->common.parent->common.aml_opcode) { + case AML_RETURN_OP: + + /* Never delete the return value associated with a return opcode */ + + goto result_used; + + case AML_IF_OP: + case AML_WHILE_OP: + + /* + * If we are executing the predicate AND this is the predicate op, + * we will use the return value + */ + if ((walk_state->control_state->common.state == + ACPI_CONTROL_PREDICATE_EXECUTING) + && (walk_state->control_state->control. + predicate_op == op)) { + goto result_used; + } + break; + + default: + /* Ignore other control opcodes */ + break; + } + + /* The general control opcode returns no result */ + + goto result_not_used; + + case AML_CLASS_CREATE: + + /* + * These opcodes allow term_arg(s) as operands and therefore + * the operands can be method calls. The result is used. + */ + goto result_used; + + case AML_CLASS_NAMED_OBJECT: + + if ((op->common.parent->common.aml_opcode == AML_REGION_OP) || + (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) + || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) + || (op->common.parent->common.aml_opcode == + AML_VAR_PACKAGE_OP) + || (op->common.parent->common.aml_opcode == AML_BUFFER_OP) + || (op->common.parent->common.aml_opcode == + AML_INT_EVAL_SUBTREE_OP) + || (op->common.parent->common.aml_opcode == + AML_BANK_FIELD_OP)) { + /* + * These opcodes allow term_arg(s) as operands and therefore + * the operands can be method calls. The result is used. + */ + goto result_used; + } + + goto result_not_used; + + default: + + /* + * In all other cases. the parent will actually use the return + * object, so keep it. + */ + goto result_used; + } + + result_used: + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Result of [%s] used by Parent [%s] Op=%p\n", + acpi_ps_get_opcode_name(op->common.aml_opcode), + acpi_ps_get_opcode_name(op->common.parent->common. + aml_opcode), op)); + + return_UINT8(TRUE); + + result_not_used: + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Result of [%s] not used by Parent [%s] Op=%p\n", + acpi_ps_get_opcode_name(op->common.aml_opcode), + acpi_ps_get_opcode_name(op->common.parent->common. + aml_opcode), op)); + + return_UINT8(FALSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_delete_result_if_not_used + * + * PARAMETERS: Op - Current parse Op + * result_obj - Result of the operation + * walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Used after interpretation of an opcode. If there is an internal + * result descriptor, check if the parent opcode will actually use + * this result. If not, delete the result now so that it will + * not become orphaned. + * + ******************************************************************************/ + +void +acpi_ds_delete_result_if_not_used(union acpi_parse_object *op, + union acpi_operand_object *result_obj, + struct acpi_walk_state *walk_state) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj); + + if (!op) { + ACPI_ERROR((AE_INFO, "Null Op")); + return_VOID; + } + + if (!result_obj) { + return_VOID; + } + + if (!acpi_ds_is_result_used(op, walk_state)) { + + /* Must pop the result stack (obj_desc should be equal to result_obj) */ + + status = acpi_ds_result_pop(&obj_desc, walk_state); + if (ACPI_SUCCESS(status)) { + acpi_ut_remove_reference(result_obj); + } + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_resolve_operands + * + * PARAMETERS: walk_state - Current walk state with operands on stack + * + * RETURN: Status + * + * DESCRIPTION: Resolve all operands to their values. Used to prepare + * arguments to a control method invocation (a call from one + * method to another.) + * + ******************************************************************************/ + +acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state) +{ + u32 i; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state); + + /* + * Attempt to resolve each of the valid operands + * Method arguments are passed by reference, not by value. This means + * that the actual objects are passed, not copies of the objects. + */ + for (i = 0; i < walk_state->num_operands; i++) { + status = + acpi_ex_resolve_to_value(&walk_state->operands[i], + walk_state); + if (ACPI_FAILURE(status)) { + break; + } + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_clear_operands + * + * PARAMETERS: walk_state - Current walk state with operands on stack + * + * RETURN: None + * + * DESCRIPTION: Clear all operands on the current walk state operand stack. + * + ******************************************************************************/ + +void acpi_ds_clear_operands(struct acpi_walk_state *walk_state) +{ + u32 i; + + ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state); + + /* Remove a reference on each operand on the stack */ + + for (i = 0; i < walk_state->num_operands; i++) { + /* + * Remove a reference to all operands, including both + * "Arguments" and "Targets". + */ + acpi_ut_remove_reference(walk_state->operands[i]); + walk_state->operands[i] = NULL; + } + + walk_state->num_operands = 0; + return_VOID; +} +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ds_create_operand + * + * PARAMETERS: walk_state - Current walk state + * Arg - Parse object for the argument + * arg_index - Which argument (zero based) + * + * RETURN: Status + * + * DESCRIPTION: Translate a parse tree object that is an argument to an AML + * opcode to the equivalent interpreter object. This may include + * looking up a name or entering a new name into the internal + * namespace. + * + ******************************************************************************/ + +acpi_status +acpi_ds_create_operand(struct acpi_walk_state *walk_state, + union acpi_parse_object *arg, u32 arg_index) +{ + acpi_status status = AE_OK; + char *name_string; + u32 name_length; + union acpi_operand_object *obj_desc; + union acpi_parse_object *parent_op; + u16 opcode; + acpi_interpreter_mode interpreter_mode; + const struct acpi_opcode_info *op_info; + + ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg); + + /* A valid name must be looked up in the namespace */ + + if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && + (arg->common.value.string) && + !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", + arg)); + + /* Get the entire name string from the AML stream */ + + status = + acpi_ex_get_name_string(ACPI_TYPE_ANY, + arg->common.value.buffer, + &name_string, &name_length); + + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* All prefixes have been handled, and the name is in name_string */ + + /* + * Special handling for buffer_field declarations. This is a deferred + * opcode that unfortunately defines the field name as the last + * parameter instead of the first. We get here when we are performing + * the deferred execution, so the actual name of the field is already + * in the namespace. We don't want to attempt to look it up again + * because we may be executing in a different scope than where the + * actual opcode exists. + */ + if ((walk_state->deferred_node) && + (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) + && (arg_index == + (u32) ((walk_state->opcode == + AML_CREATE_FIELD_OP) ? 3 : 2))) { + obj_desc = + ACPI_CAST_PTR(union acpi_operand_object, + walk_state->deferred_node); + status = AE_OK; + } else { /* All other opcodes */ + + /* + * Differentiate between a namespace "create" operation + * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. + * IMODE_EXECUTE) in order to support the creation of + * namespace objects during the execution of control methods. + */ + parent_op = arg->common.parent; + op_info = + acpi_ps_get_opcode_info(parent_op->common. + aml_opcode); + if ((op_info->flags & AML_NSNODE) + && (parent_op->common.aml_opcode != + AML_INT_METHODCALL_OP) + && (parent_op->common.aml_opcode != AML_REGION_OP) + && (parent_op->common.aml_opcode != + AML_INT_NAMEPATH_OP)) { + + /* Enter name into namespace if not found */ + + interpreter_mode = ACPI_IMODE_LOAD_PASS2; + } else { + /* Return a failure if name not found */ + + interpreter_mode = ACPI_IMODE_EXECUTE; + } + + status = + acpi_ns_lookup(walk_state->scope_info, name_string, + ACPI_TYPE_ANY, interpreter_mode, + ACPI_NS_SEARCH_PARENT | + ACPI_NS_DONT_OPEN_SCOPE, walk_state, + ACPI_CAST_INDIRECT_PTR(struct + acpi_namespace_node, + &obj_desc)); + /* + * The only case where we pass through (ignore) a NOT_FOUND + * error is for the cond_ref_of opcode. + */ + if (status == AE_NOT_FOUND) { + if (parent_op->common.aml_opcode == + AML_COND_REF_OF_OP) { + /* + * For the Conditional Reference op, it's OK if + * the name is not found; We just need a way to + * indicate this to the interpreter, set the + * object to the root + */ + obj_desc = ACPI_CAST_PTR(union + acpi_operand_object, + acpi_gbl_root_node); + status = AE_OK; + } else { + /* + * We just plain didn't find it -- which is a + * very serious error at this point + */ + status = AE_AML_NAME_NOT_FOUND; + } + } + + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(name_string, status); + } + } + + /* Free the namestring created above */ + + ACPI_FREE(name_string); + + /* Check status from the lookup */ + + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Put the resulting object onto the current object stack */ + + status = acpi_ds_obj_stack_push(obj_desc, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object + (obj_desc, walk_state)); + } else { + /* Check for null name case */ + + if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && + !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { + /* + * If the name is null, this means that this is an + * optional result parameter that was not specified + * in the original ASL. Create a Zero Constant for a + * placeholder. (Store to a constant is a Noop.) + */ + opcode = AML_ZERO_OP; /* Has no arguments! */ + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Null namepath: Arg=%p\n", arg)); + } else { + opcode = arg->common.aml_opcode; + } + + /* Get the object type of the argument */ + + op_info = acpi_ps_get_opcode_info(opcode); + if (op_info->object_type == ACPI_TYPE_INVALID) { + return_ACPI_STATUS(AE_NOT_IMPLEMENTED); + } + + if ((op_info->flags & AML_HAS_RETVAL) + || (arg->common.flags & ACPI_PARSEOP_IN_STACK)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Argument previously created, already stacked\n")); + + ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object + (walk_state-> + operands[walk_state->num_operands - + 1], walk_state)); + + /* + * Use value that was already previously returned + * by the evaluation of this argument + */ + status = acpi_ds_result_pop(&obj_desc, walk_state); + if (ACPI_FAILURE(status)) { + /* + * Only error is underflow, and this indicates + * a missing or null operand! + */ + ACPI_EXCEPTION((AE_INFO, status, + "Missing or null operand")); + return_ACPI_STATUS(status); + } + } else { + /* Create an ACPI_INTERNAL_OBJECT for the argument */ + + obj_desc = + acpi_ut_create_internal_object(op_info-> + object_type); + if (!obj_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Initialize the new object */ + + status = + acpi_ds_init_object_from_op(walk_state, arg, opcode, + &obj_desc); + if (ACPI_FAILURE(status)) { + acpi_ut_delete_object_desc(obj_desc); + return_ACPI_STATUS(status); + } + } + + /* Put the operand object on the object stack */ + + status = acpi_ds_obj_stack_push(obj_desc, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object + (obj_desc, walk_state)); + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_create_operands + * + * PARAMETERS: walk_state - Current state + * first_arg - First argument of a parser argument tree + * + * RETURN: Status + * + * DESCRIPTION: Convert an operator's arguments from a parse tree format to + * namespace objects and place those argument object on the object + * stack in preparation for evaluation by the interpreter. + * + ******************************************************************************/ + +acpi_status +acpi_ds_create_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *first_arg) +{ + acpi_status status = AE_OK; + union acpi_parse_object *arg; + union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS]; + u32 arg_count = 0; + u32 index = walk_state->num_operands; + u32 i; + + ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); + + /* Get all arguments in the list */ + + arg = first_arg; + while (arg) { + if (index >= ACPI_OBJ_NUM_OPERANDS) { + return_ACPI_STATUS(AE_BAD_DATA); + } + + arguments[index] = arg; + walk_state->operands[index] = NULL; + + /* Move on to next argument, if any */ + + arg = arg->common.next; + arg_count++; + index++; + } + + index--; + + /* It is the appropriate order to get objects from the Result stack */ + + for (i = 0; i < arg_count; i++) { + arg = arguments[index]; + + /* Force the filling of the operand stack in inverse order */ + + walk_state->operand_index = (u8) index; + + status = acpi_ds_create_operand(walk_state, arg, index); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + index--; + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Arg #%d (%p) done, Arg1=%p\n", index, arg, + first_arg)); + } + + return_ACPI_STATUS(status); + + cleanup: + /* + * We must undo everything done above; meaning that we must + * pop everything off of the operand stack and delete those + * objects + */ + acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); + + ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index)); + return_ACPI_STATUS(status); +} + +/***************************************************************************** + * + * FUNCTION: acpi_ds_evaluate_name_path + * + * PARAMETERS: walk_state - Current state of the parse tree walk, + * the opcode of current operation should be + * AML_INT_NAMEPATH_OP + * + * RETURN: Status + * + * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent + * interpreter object, convert it to value, if needed, duplicate + * it, if needed, and push it onto the current result stack. + * + ****************************************************************************/ + +acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_parse_object *op = walk_state->op; + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *new_obj_desc; + u8 type; + + ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state); + + if (!op->common.parent) { + + /* This happens after certain exception processing */ + + goto exit; + } + + if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) { + + /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */ + + goto exit; + } + + status = acpi_ds_create_operand(walk_state, op, 0); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (op->common.flags & ACPI_PARSEOP_TARGET) { + new_obj_desc = *operand; + goto push_result; + } + + type = ACPI_GET_OBJECT_TYPE(*operand); + + status = acpi_ex_resolve_to_value(operand, walk_state); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (type == ACPI_TYPE_INTEGER) { + + /* It was incremented by acpi_ex_resolve_to_value */ + + acpi_ut_remove_reference(*operand); + + status = + acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc, + walk_state); + if (ACPI_FAILURE(status)) { + goto exit; + } + } else { + /* + * The object either was anew created or is + * a Namespace node - don't decrement it. + */ + new_obj_desc = *operand; + } + + /* Cleanup for name-path operand */ + + status = acpi_ds_obj_stack_pop(1, walk_state); + if (ACPI_FAILURE(status)) { + walk_state->result_obj = new_obj_desc; + goto exit; + } + + push_result: + + walk_state->result_obj = new_obj_desc; + + status = acpi_ds_result_push(walk_state->result_obj, walk_state); + if (ACPI_SUCCESS(status)) { + + /* Force to take it from stack */ + + op->common.flags |= ACPI_PARSEOP_IN_STACK; + } + + exit: + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c new file mode 100644 index 000000000000..2482cbd37f25 --- /dev/null +++ b/drivers/acpi/acpica/dswexec.c @@ -0,0 +1,746 @@ +/****************************************************************************** + * + * Module Name: dswexec - Dispatcher method execution callbacks; + * dispatch to interpreter. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dswexec") + +/* + * Dispatch table for opcode classes + */ +static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch[] = { + acpi_ex_opcode_0A_0T_1R, + acpi_ex_opcode_1A_0T_0R, + acpi_ex_opcode_1A_0T_1R, + acpi_ex_opcode_1A_1T_0R, + acpi_ex_opcode_1A_1T_1R, + acpi_ex_opcode_2A_0T_0R, + acpi_ex_opcode_2A_0T_1R, + acpi_ex_opcode_2A_1T_1R, + acpi_ex_opcode_2A_2T_1R, + acpi_ex_opcode_3A_0T_0R, + acpi_ex_opcode_3A_1T_1R, + acpi_ex_opcode_6A_0T_1R +}; + +/***************************************************************************** + * + * FUNCTION: acpi_ds_get_predicate_value + * + * PARAMETERS: walk_state - Current state of the parse tree walk + * result_obj - if non-zero, pop result from result stack + * + * RETURN: Status + * + * DESCRIPTION: Get the result of a predicate evaluation + * + ****************************************************************************/ + +acpi_status +acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, + union acpi_operand_object *result_obj) +{ + acpi_status status = AE_OK; + union acpi_operand_object *obj_desc; + union acpi_operand_object *local_obj_desc = NULL; + + ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state); + + walk_state->control_state->common.state = 0; + + if (result_obj) { + status = acpi_ds_result_pop(&obj_desc, walk_state); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not get result from predicate evaluation")); + + return_ACPI_STATUS(status); + } + } else { + status = acpi_ds_create_operand(walk_state, walk_state->op, 0); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = + acpi_ex_resolve_to_value(&walk_state->operands[0], + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + obj_desc = walk_state->operands[0]; + } + + if (!obj_desc) { + ACPI_ERROR((AE_INFO, + "No predicate ObjDesc=%p State=%p", + obj_desc, walk_state)); + + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + /* + * Result of predicate evaluation must be an Integer + * object. Implicitly convert the argument if necessary. + */ + status = acpi_ex_convert_to_integer(obj_desc, &local_obj_desc, 16); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) { + ACPI_ERROR((AE_INFO, + "Bad predicate (not an integer) ObjDesc=%p State=%p Type=%X", + obj_desc, walk_state, + ACPI_GET_OBJECT_TYPE(obj_desc))); + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + /* Truncate the predicate to 32-bits if necessary */ + + acpi_ex_truncate_for32bit_table(local_obj_desc); + + /* + * Save the result of the predicate evaluation on + * the control stack + */ + if (local_obj_desc->integer.value) { + walk_state->control_state->common.value = TRUE; + } else { + /* + * Predicate is FALSE, we will just toss the + * rest of the package + */ + walk_state->control_state->common.value = FALSE; + status = AE_CTRL_FALSE; + } + + /* Predicate can be used for an implicit return value */ + + (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE); + + cleanup: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n", + walk_state->control_state->common.value, + walk_state->op)); + + /* Break to debugger to display result */ + + ACPI_DEBUGGER_EXEC(acpi_db_display_result_object + (local_obj_desc, walk_state)); + + /* + * Delete the predicate result object (we know that + * we don't need it anymore) + */ + if (local_obj_desc != obj_desc) { + acpi_ut_remove_reference(local_obj_desc); + } + acpi_ut_remove_reference(obj_desc); + + walk_state->control_state->common.state = ACPI_CONTROL_NORMAL; + return_ACPI_STATUS(status); +} + +/***************************************************************************** + * + * FUNCTION: acpi_ds_exec_begin_op + * + * PARAMETERS: walk_state - Current state of the parse tree walk + * out_op - Where to return op if a new one is created + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the execution of control + * methods. This is where most operators and operands are + * dispatched to the interpreter. + * + ****************************************************************************/ + +acpi_status +acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **out_op) +{ + union acpi_parse_object *op; + acpi_status status = AE_OK; + u32 opcode_class; + + ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state); + + op = walk_state->op; + if (!op) { + status = acpi_ds_load2_begin_op(walk_state, out_op); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + + op = *out_op; + walk_state->op = op; + walk_state->opcode = op->common.aml_opcode; + walk_state->op_info = + acpi_ps_get_opcode_info(op->common.aml_opcode); + + if (acpi_ns_opens_scope(walk_state->op_info->object_type)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "(%s) Popping scope for Op %p\n", + acpi_ut_get_type_name(walk_state-> + op_info-> + object_type), + op)); + + status = acpi_ds_scope_stack_pop(walk_state); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + } + } + + if (op == walk_state->origin) { + if (out_op) { + *out_op = op; + } + + return_ACPI_STATUS(AE_OK); + } + + /* + * If the previous opcode was a conditional, this opcode + * must be the beginning of the associated predicate. + * Save this knowledge in the current scope descriptor + */ + if ((walk_state->control_state) && + (walk_state->control_state->common.state == + ACPI_CONTROL_CONDITIONAL_EXECUTING)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Exec predicate Op=%p State=%p\n", op, + walk_state)); + + walk_state->control_state->common.state = + ACPI_CONTROL_PREDICATE_EXECUTING; + + /* Save start of predicate */ + + walk_state->control_state->control.predicate_op = op; + } + + opcode_class = walk_state->op_info->class; + + /* We want to send namepaths to the load code */ + + if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { + opcode_class = AML_CLASS_NAMED_OBJECT; + } + + /* + * Handle the opcode based upon the opcode type + */ + switch (opcode_class) { + case AML_CLASS_CONTROL: + + status = acpi_ds_exec_begin_control_op(walk_state, op); + break; + + case AML_CLASS_NAMED_OBJECT: + + if (walk_state->walk_type & ACPI_WALK_METHOD) { + /* + * Found a named object declaration during method execution; + * we must enter this object into the namespace. The created + * object is temporary and will be deleted upon completion of + * the execution of this method. + */ + status = acpi_ds_load2_begin_op(walk_state, NULL); + } + + break; + + case AML_CLASS_EXECUTE: + case AML_CLASS_CREATE: + + break; + + default: + break; + } + + /* Nothing to do here during method execution */ + + return_ACPI_STATUS(status); + + error_exit: + status = acpi_ds_method_error(status, walk_state); + return_ACPI_STATUS(status); +} + +/***************************************************************************** + * + * FUNCTION: acpi_ds_exec_end_op + * + * PARAMETERS: walk_state - Current state of the parse tree walk + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the execution of control + * methods. The only thing we really need to do here is to + * notice the beginning of IF, ELSE, and WHILE blocks. + * + ****************************************************************************/ + +acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) +{ + union acpi_parse_object *op; + acpi_status status = AE_OK; + u32 op_type; + u32 op_class; + union acpi_parse_object *next_op; + union acpi_parse_object *first_arg; + + ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state); + + op = walk_state->op; + op_type = walk_state->op_info->type; + op_class = walk_state->op_info->class; + + if (op_class == AML_CLASS_UNKNOWN) { + ACPI_ERROR((AE_INFO, "Unknown opcode %X", + op->common.aml_opcode)); + return_ACPI_STATUS(AE_NOT_IMPLEMENTED); + } + + first_arg = op->common.value.arg; + + /* Init the walk state */ + + walk_state->num_operands = 0; + walk_state->operand_index = 0; + walk_state->return_desc = NULL; + walk_state->result_obj = NULL; + + /* Call debugger for single step support (DEBUG build only) */ + + ACPI_DEBUGGER_EXEC(status = + acpi_db_single_step(walk_state, op, op_class)); + ACPI_DEBUGGER_EXEC(if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status);} + ) ; + + /* Decode the Opcode Class */ + + switch (op_class) { + case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ + + if (walk_state->opcode == AML_INT_NAMEPATH_OP) { + status = acpi_ds_evaluate_name_path(walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + } + break; + + case AML_CLASS_EXECUTE: /* Most operators with arguments */ + + /* Build resolved operand stack */ + + status = acpi_ds_create_operands(walk_state, first_arg); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* + * All opcodes require operand resolution, with the only exceptions + * being the object_type and size_of operators. + */ + if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) { + + /* Resolve all operands */ + + status = acpi_ex_resolve_operands(walk_state->opcode, + &(walk_state-> + operands + [walk_state-> + num_operands - 1]), + walk_state); + } + + if (ACPI_SUCCESS(status)) { + /* + * Dispatch the request to the appropriate interpreter handler + * routine. There is one routine per opcode "type" based upon the + * number of opcode arguments and return type. + */ + status = + acpi_gbl_op_type_dispatch[op_type] (walk_state); + } else { + /* + * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the + * Local is uninitialized. + */ + if ((status == AE_AML_UNINITIALIZED_LOCAL) && + (walk_state->opcode == AML_STORE_OP) && + (walk_state->operands[0]->common.type == + ACPI_TYPE_LOCAL_REFERENCE) + && (walk_state->operands[1]->common.type == + ACPI_TYPE_LOCAL_REFERENCE) + && (walk_state->operands[0]->reference.class == + walk_state->operands[1]->reference.class) + && (walk_state->operands[0]->reference.value == + walk_state->operands[1]->reference.value)) { + status = AE_OK; + } else { + ACPI_EXCEPTION((AE_INFO, status, + "While resolving operands for [%s]", + acpi_ps_get_opcode_name + (walk_state->opcode))); + } + } + + /* Always delete the argument objects and clear the operand stack */ + + acpi_ds_clear_operands(walk_state); + + /* + * If a result object was returned from above, push it on the + * current result stack + */ + if (ACPI_SUCCESS(status) && walk_state->result_obj) { + status = + acpi_ds_result_push(walk_state->result_obj, + walk_state); + } + break; + + default: + + switch (op_type) { + case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ + + /* 1 Operand, 0 external_result, 0 internal_result */ + + status = acpi_ds_exec_end_control_op(walk_state, op); + + break; + + case AML_TYPE_METHOD_CALL: + + /* + * If the method is referenced from within a package + * declaration, it is not a invocation of the method, just + * a reference to it. + */ + if ((op->asl.parent) && + ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) + || (op->asl.parent->asl.aml_opcode == + AML_VAR_PACKAGE_OP))) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Method Reference in a Package, Op=%p\n", + op)); + + op->common.node = + (struct acpi_namespace_node *)op->asl.value. + arg->asl.node; + acpi_ut_add_reference(op->asl.value.arg->asl. + node->object); + return_ACPI_STATUS(AE_OK); + } + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Method invocation, Op=%p\n", op)); + + /* + * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains + * the method Node pointer + */ + /* next_op points to the op that holds the method name */ + + next_op = first_arg; + + /* next_op points to first argument op */ + + next_op = next_op->common.next; + + /* + * Get the method's arguments and put them on the operand stack + */ + status = acpi_ds_create_operands(walk_state, next_op); + if (ACPI_FAILURE(status)) { + break; + } + + /* + * Since the operands will be passed to another control method, + * we must resolve all local references here (Local variables, + * arguments to *this* method, etc.) + */ + status = acpi_ds_resolve_operands(walk_state); + if (ACPI_FAILURE(status)) { + + /* On error, clear all resolved operands */ + + acpi_ds_clear_operands(walk_state); + break; + } + + /* + * Tell the walk loop to preempt this running method and + * execute the new method + */ + status = AE_CTRL_TRANSFER; + + /* + * Return now; we don't want to disturb anything, + * especially the operand count! + */ + return_ACPI_STATUS(status); + + case AML_TYPE_CREATE_FIELD: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Executing CreateField Buffer/Index Op=%p\n", + op)); + + status = acpi_ds_load2_end_op(walk_state); + if (ACPI_FAILURE(status)) { + break; + } + + status = + acpi_ds_eval_buffer_field_operands(walk_state, op); + break; + + case AML_TYPE_CREATE_OBJECT: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Executing CreateObject (Buffer/Package) Op=%p\n", + op)); + + switch (op->common.parent->common.aml_opcode) { + case AML_NAME_OP: + + /* + * Put the Node on the object stack (Contains the ACPI Name + * of this object) + */ + walk_state->operands[0] = + (void *)op->common.parent->common.node; + walk_state->num_operands = 1; + + status = acpi_ds_create_node(walk_state, + op->common.parent-> + common.node, + op->common.parent); + if (ACPI_FAILURE(status)) { + break; + } + + /* Fall through */ + /*lint -fallthrough */ + + case AML_INT_EVAL_SUBTREE_OP: + + status = + acpi_ds_eval_data_object_operands + (walk_state, op, + acpi_ns_get_attached_object(op->common. + parent->common. + node)); + break; + + default: + + status = + acpi_ds_eval_data_object_operands + (walk_state, op, NULL); + break; + } + + /* + * If a result object was returned from above, push it on the + * current result stack + */ + if (walk_state->result_obj) { + status = + acpi_ds_result_push(walk_state->result_obj, + walk_state); + } + break; + + case AML_TYPE_NAMED_FIELD: + case AML_TYPE_NAMED_COMPLEX: + case AML_TYPE_NAMED_SIMPLE: + case AML_TYPE_NAMED_NO_OBJ: + + status = acpi_ds_load2_end_op(walk_state); + if (ACPI_FAILURE(status)) { + break; + } + + if (op->common.aml_opcode == AML_REGION_OP) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Executing OpRegion Address/Length Op=%p\n", + op)); + + status = + acpi_ds_eval_region_operands(walk_state, + op); + if (ACPI_FAILURE(status)) { + break; + } + } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Executing DataTableRegion Strings Op=%p\n", + op)); + + status = + acpi_ds_eval_table_region_operands + (walk_state, op); + if (ACPI_FAILURE(status)) { + break; + } + } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Executing BankField Op=%p\n", + op)); + + status = + acpi_ds_eval_bank_field_operands(walk_state, + op); + if (ACPI_FAILURE(status)) { + break; + } + } + break; + + case AML_TYPE_UNDEFINED: + + ACPI_ERROR((AE_INFO, + "Undefined opcode type Op=%p", op)); + return_ACPI_STATUS(AE_NOT_IMPLEMENTED); + + case AML_TYPE_BOGUS: + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Internal opcode=%X type Op=%p\n", + walk_state->opcode, op)); + break; + + default: + + ACPI_ERROR((AE_INFO, + "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p", + op_class, op_type, op->common.aml_opcode, + op)); + + status = AE_NOT_IMPLEMENTED; + break; + } + } + + /* + * ACPI 2.0 support for 64-bit integers: Truncate numeric + * result value if we are executing from a 32-bit ACPI table + */ + acpi_ex_truncate_for32bit_table(walk_state->result_obj); + + /* + * Check if we just completed the evaluation of a + * conditional predicate + */ + if ((ACPI_SUCCESS(status)) && + (walk_state->control_state) && + (walk_state->control_state->common.state == + ACPI_CONTROL_PREDICATE_EXECUTING) && + (walk_state->control_state->control.predicate_op == op)) { + status = + acpi_ds_get_predicate_value(walk_state, + walk_state->result_obj); + walk_state->result_obj = NULL; + } + + cleanup: + + if (walk_state->result_obj) { + + /* Break to debugger to display result */ + + ACPI_DEBUGGER_EXEC(acpi_db_display_result_object + (walk_state->result_obj, walk_state)); + + /* + * Delete the result op if and only if: + * Parent will not use the result -- such as any + * non-nested type2 op in a method (parent will be method) + */ + acpi_ds_delete_result_if_not_used(op, walk_state->result_obj, + walk_state); + } +#ifdef _UNDER_DEVELOPMENT + + if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) { + acpi_db_method_end(walk_state); + } +#endif + + /* Invoke exception handler on error */ + + if (ACPI_FAILURE(status)) { + status = acpi_ds_method_error(status, walk_state); + } + + /* Always clear the object stack */ + + walk_state->num_operands = 0; + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c new file mode 100644 index 000000000000..2d71ceda3d56 --- /dev/null +++ b/drivers/acpi/acpica/dswload.c @@ -0,0 +1,1203 @@ +/****************************************************************************** + * + * Module Name: dswload - Dispatcher namespace load callbacks + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef ACPI_ASL_COMPILER +#include +#endif + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dswload") + +/******************************************************************************* + * + * FUNCTION: acpi_ds_init_callbacks + * + * PARAMETERS: walk_state - Current state of the parse tree walk + * pass_number - 1, 2, or 3 + * + * RETURN: Status + * + * DESCRIPTION: Init walk state callbacks + * + ******************************************************************************/ +acpi_status +acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) +{ + + switch (pass_number) { + case 1: + walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | + ACPI_PARSE_DELETE_TREE; + walk_state->descending_callback = acpi_ds_load1_begin_op; + walk_state->ascending_callback = acpi_ds_load1_end_op; + break; + + case 2: + walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | + ACPI_PARSE_DELETE_TREE; + walk_state->descending_callback = acpi_ds_load2_begin_op; + walk_state->ascending_callback = acpi_ds_load2_end_op; + break; + + case 3: +#ifndef ACPI_NO_METHOD_EXECUTION + walk_state->parse_flags |= ACPI_PARSE_EXECUTE | + ACPI_PARSE_DELETE_TREE; + walk_state->descending_callback = acpi_ds_exec_begin_op; + walk_state->ascending_callback = acpi_ds_exec_end_op; +#endif + break; + + default: + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_load1_begin_op + * + * PARAMETERS: walk_state - Current state of the parse tree walk + * out_op - Where to return op if a new one is created + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * + ******************************************************************************/ + +acpi_status +acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, + union acpi_parse_object ** out_op) +{ + union acpi_parse_object *op; + struct acpi_namespace_node *node; + acpi_status status; + acpi_object_type object_type; + char *path; + u32 flags; + + ACPI_FUNCTION_TRACE(ds_load1_begin_op); + + op = walk_state->op; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, + walk_state)); + + /* We are only interested in opcodes that have an associated name */ + + if (op) { + if (!(walk_state->op_info->flags & AML_NAMED)) { + *out_op = op; + return_ACPI_STATUS(AE_OK); + } + + /* Check if this object has already been installed in the namespace */ + + if (op->common.node) { + *out_op = op; + return_ACPI_STATUS(AE_OK); + } + } + + path = acpi_ps_get_next_namestring(&walk_state->parser_state); + + /* Map the raw opcode into an internal object type */ + + object_type = walk_state->op_info->object_type; + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "State=%p Op=%p [%s]\n", walk_state, op, + acpi_ut_get_type_name(object_type))); + + switch (walk_state->opcode) { + case AML_SCOPE_OP: + + /* + * The target name of the Scope() operator must exist at this point so + * that we can actually open the scope to enter new names underneath it. + * Allow search-to-root for single namesegs. + */ + status = + acpi_ns_lookup(walk_state->scope_info, path, object_type, + ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, + walk_state, &(node)); +#ifdef ACPI_ASL_COMPILER + if (status == AE_NOT_FOUND) { + /* + * Table disassembly: + * Target of Scope() not found. Generate an External for it, and + * insert the name into the namespace. + */ + acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0); + status = + acpi_ns_lookup(walk_state->scope_info, path, + object_type, ACPI_IMODE_LOAD_PASS1, + ACPI_NS_SEARCH_PARENT, walk_state, + &node); + } +#endif + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(path, status); + return_ACPI_STATUS(status); + } + + /* + * Check to make sure that the target is + * one of the opcodes that actually opens a scope + */ + switch (node->type) { + case ACPI_TYPE_ANY: + case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* These are acceptable types */ + break; + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * These types we will allow, but we will change the type. This + * enables some existing code of the form: + * + * Name (DEB, 0) + * Scope (DEB) { ... } + * + * Note: silently change the type here. On the second pass, we will report + * a warning + */ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", + path, + acpi_ut_get_type_name(node->type))); + + node->type = ACPI_TYPE_ANY; + walk_state->scope_info->common.value = ACPI_TYPE_ANY; + break; + + default: + + /* All other types are an error */ + + ACPI_ERROR((AE_INFO, + "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)", + acpi_ut_get_type_name(node->type), path)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + break; + + default: + /* + * For all other named opcodes, we will enter the name into + * the namespace. + * + * Setup the search flags. + * Since we are entering a name into the namespace, we do not want to + * enable the search-to-root upsearch. + * + * There are only two conditions where it is acceptable that the name + * already exists: + * 1) the Scope() operator can reopen a scoping object that was + * previously defined (Scope, Method, Device, etc.) + * 2) Whenever we are parsing a deferred opcode (op_region, Buffer, + * buffer_field, or Package), the name of the object is already + * in the namespace. + */ + if (walk_state->deferred_node) { + + /* This name is already in the namespace, get the node */ + + node = walk_state->deferred_node; + status = AE_OK; + break; + } + + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (walk_state->method_node) { + node = NULL; + status = AE_OK; + break; + } + + flags = ACPI_NS_NO_UPSEARCH; + if ((walk_state->opcode != AML_SCOPE_OP) && + (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) { + flags |= ACPI_NS_ERROR_IF_FOUND; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "[%s] Cannot already exist\n", + acpi_ut_get_type_name(object_type))); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "[%s] Both Find or Create allowed\n", + acpi_ut_get_type_name(object_type))); + } + + /* + * Enter the named type into the internal namespace. We enter the name + * as we go downward in the parse tree. Any necessary subobjects that + * involve arguments to the opcode must be created as we go back up the + * parse tree later. + */ + status = + acpi_ns_lookup(walk_state->scope_info, path, object_type, + ACPI_IMODE_LOAD_PASS1, flags, walk_state, + &node); + if (ACPI_FAILURE(status)) { + if (status == AE_ALREADY_EXISTS) { + + /* The name already exists in this scope */ + + if (node->flags & ANOBJ_IS_EXTERNAL) { + /* + * Allow one create on an object or segment that was + * previously declared External + */ + node->flags &= ~ANOBJ_IS_EXTERNAL; + node->type = (u8) object_type; + + /* Just retyped a node, probably will need to open a scope */ + + if (acpi_ns_opens_scope(object_type)) { + status = + acpi_ds_scope_stack_push + (node, object_type, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS + (status); + } + } + + status = AE_OK; + } + } + + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(path, status); + return_ACPI_STATUS(status); + } + } + break; + } + + /* Common exit */ + + if (!op) { + + /* Create a new op */ + + op = acpi_ps_alloc_op(walk_state->opcode); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + } + + /* Initialize the op */ + +#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) + op->named.path = ACPI_CAST_PTR(u8, path); +#endif + + if (node) { + /* + * Put the Node in the "op" object that the parser uses, so we + * can get it again quickly when this scope is closed + */ + op->common.node = node; + op->named.name = node->name.integer; + } + + acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state), + op); + *out_op = op; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_load1_end_op + * + * PARAMETERS: walk_state - Current state of the parse tree walk + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the loading of the namespace, + * both control methods and everything else. + * + ******************************************************************************/ + +acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) +{ + union acpi_parse_object *op; + acpi_object_type object_type; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ds_load1_end_op); + + op = walk_state->op; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, + walk_state)); + + /* We are only interested in opcodes that have an associated name */ + + if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the object type to determine if we should pop the scope */ + + object_type = walk_state->op_info->object_type; + +#ifndef ACPI_NO_METHOD_EXECUTION + if (walk_state->op_info->flags & AML_FIELD) { + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (!walk_state->method_node) { + if (walk_state->opcode == AML_FIELD_OP || + walk_state->opcode == AML_BANK_FIELD_OP || + walk_state->opcode == AML_INDEX_FIELD_OP) { + status = + acpi_ds_init_field_objects(op, walk_state); + } + } + return_ACPI_STATUS(status); + } + + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (!walk_state->method_node) { + if (op->common.aml_opcode == AML_REGION_OP) { + status = + acpi_ex_create_region(op->named.data, + op->named.length, + (acpi_adr_space_type) ((op-> + common. + value. + arg)-> + common. + value. + integer), + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { + status = + acpi_ex_create_region(op->named.data, + op->named.length, + REGION_DATA_TABLE, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + } +#endif + + if (op->common.aml_opcode == AML_NAME_OP) { + + /* For Name opcode, get the object type from the argument */ + + if (op->common.value.arg) { + object_type = (acpi_ps_get_opcode_info((op->common. + value.arg)-> + common. + aml_opcode))-> + object_type; + + /* Set node type if we have a namespace node */ + + if (op->common.node) { + op->common.node->type = (u8) object_type; + } + } + } + + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (!walk_state->method_node) { + if (op->common.aml_opcode == AML_METHOD_OP) { + /* + * method_op pkg_length name_string method_flags term_list + * + * Note: We must create the method node/object pair as soon as we + * see the method declaration. This allows later pass1 parsing + * of invocations of the method (need to know the number of + * arguments.) + */ + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "LOADING-Method: State=%p Op=%p NamedObj=%p\n", + walk_state, op, op->named.node)); + + if (!acpi_ns_get_attached_object(op->named.node)) { + walk_state->operands[0] = + ACPI_CAST_PTR(void, op->named.node); + walk_state->num_operands = 1; + + status = + acpi_ds_create_operands(walk_state, + op->common.value. + arg); + if (ACPI_SUCCESS(status)) { + status = + acpi_ex_create_method(op->named. + data, + op->named. + length, + walk_state); + } + + walk_state->operands[0] = NULL; + walk_state->num_operands = 0; + + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + } + } + + /* Pop the scope stack (only if loading a table) */ + + if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "(%s): Popping scope for Op %p\n", + acpi_ut_get_type_name(object_type), op)); + + status = acpi_ds_scope_stack_pop(walk_state); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_load2_begin_op + * + * PARAMETERS: walk_state - Current state of the parse tree walk + * out_op - Wher to return op if a new one is created + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * + ******************************************************************************/ + +acpi_status +acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **out_op) +{ + union acpi_parse_object *op; + struct acpi_namespace_node *node; + acpi_status status; + acpi_object_type object_type; + char *buffer_ptr; + u32 flags; + + ACPI_FUNCTION_TRACE(ds_load2_begin_op); + + op = walk_state->op; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, + walk_state)); + + if (op) { + if ((walk_state->control_state) && + (walk_state->control_state->common.state == + ACPI_CONTROL_CONDITIONAL_EXECUTING)) { + + /* We are executing a while loop outside of a method */ + + status = acpi_ds_exec_begin_op(walk_state, out_op); + return_ACPI_STATUS(status); + } + + /* We only care about Namespace opcodes here */ + + if ((!(walk_state->op_info->flags & AML_NSOPCODE) && + (walk_state->opcode != AML_INT_NAMEPATH_OP)) || + (!(walk_state->op_info->flags & AML_NAMED))) { +#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE + if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || + (walk_state->op_info->class == AML_CLASS_CONTROL)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Begin/EXEC: %s (fl %8.8X)\n", + walk_state->op_info->name, + walk_state->op_info->flags)); + + /* Executing a type1 or type2 opcode outside of a method */ + + status = + acpi_ds_exec_begin_op(walk_state, out_op); + return_ACPI_STATUS(status); + } +#endif + return_ACPI_STATUS(AE_OK); + } + + /* Get the name we are going to enter or lookup in the namespace */ + + if (walk_state->opcode == AML_INT_NAMEPATH_OP) { + + /* For Namepath op, get the path string */ + + buffer_ptr = op->common.value.string; + if (!buffer_ptr) { + + /* No name, just exit */ + + return_ACPI_STATUS(AE_OK); + } + } else { + /* Get name from the op */ + + buffer_ptr = ACPI_CAST_PTR(char, &op->named.name); + } + } else { + /* Get the namestring from the raw AML */ + + buffer_ptr = + acpi_ps_get_next_namestring(&walk_state->parser_state); + } + + /* Map the opcode into an internal object type */ + + object_type = walk_state->op_info->object_type; + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "State=%p Op=%p Type=%X\n", walk_state, op, + object_type)); + + switch (walk_state->opcode) { + case AML_FIELD_OP: + case AML_BANK_FIELD_OP: + case AML_INDEX_FIELD_OP: + + node = NULL; + status = AE_OK; + break; + + case AML_INT_NAMEPATH_OP: + /* + * The name_path is an object reference to an existing object. + * Don't enter the name into the namespace, but look it up + * for use later. + */ + status = + acpi_ns_lookup(walk_state->scope_info, buffer_ptr, + object_type, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, &(node)); + break; + + case AML_SCOPE_OP: + /* + * The Path is an object reference to an existing object. + * Don't enter the name into the namespace, but look it up + * for use later. + */ + status = + acpi_ns_lookup(walk_state->scope_info, buffer_ptr, + object_type, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT, walk_state, &(node)); + if (ACPI_FAILURE(status)) { +#ifdef ACPI_ASL_COMPILER + if (status == AE_NOT_FOUND) { + status = AE_OK; + } else { + ACPI_ERROR_NAMESPACE(buffer_ptr, status); + } +#else + ACPI_ERROR_NAMESPACE(buffer_ptr, status); +#endif + return_ACPI_STATUS(status); + } + + /* + * We must check to make sure that the target is + * one of the opcodes that actually opens a scope + */ + switch (node->type) { + case ACPI_TYPE_ANY: + case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* These are acceptable types */ + break; + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * These types we will allow, but we will change the type. This + * enables some existing code of the form: + * + * Name (DEB, 0) + * Scope (DEB) { ... } + */ + ACPI_WARNING((AE_INFO, + "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)", + buffer_ptr, + acpi_ut_get_type_name(node->type))); + + node->type = ACPI_TYPE_ANY; + walk_state->scope_info->common.value = ACPI_TYPE_ANY; + break; + + default: + + /* All other types are an error */ + + ACPI_ERROR((AE_INFO, + "Invalid type (%s) for target of Scope operator [%4.4s]", + acpi_ut_get_type_name(node->type), + buffer_ptr)); + + return (AE_AML_OPERAND_TYPE); + } + break; + + default: + + /* All other opcodes */ + + if (op && op->common.node) { + + /* This op/node was previously entered into the namespace */ + + node = op->common.node; + + if (acpi_ns_opens_scope(object_type)) { + status = + acpi_ds_scope_stack_push(node, object_type, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + return_ACPI_STATUS(AE_OK); + } + + /* + * Enter the named type into the internal namespace. We enter the name + * as we go downward in the parse tree. Any necessary subobjects that + * involve arguments to the opcode must be created as we go back up the + * parse tree later. + * + * Note: Name may already exist if we are executing a deferred opcode. + */ + if (walk_state->deferred_node) { + + /* This name is already in the namespace, get the node */ + + node = walk_state->deferred_node; + status = AE_OK; + break; + } + + flags = ACPI_NS_NO_UPSEARCH; + if (walk_state->pass_number == ACPI_IMODE_EXECUTE) { + + /* Execution mode, node cannot already exist, node is temporary */ + + flags |= (ACPI_NS_ERROR_IF_FOUND | ACPI_NS_TEMPORARY); + } + + /* Add new entry or lookup existing entry */ + + status = + acpi_ns_lookup(walk_state->scope_info, buffer_ptr, + object_type, ACPI_IMODE_LOAD_PASS2, flags, + walk_state, &node); + + if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "***New Node [%4.4s] %p is temporary\n", + acpi_ut_get_node_name(node), node)); + } + break; + } + + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(buffer_ptr, status); + return_ACPI_STATUS(status); + } + + if (!op) { + + /* Create a new op */ + + op = acpi_ps_alloc_op(walk_state->opcode); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Initialize the new op */ + + if (node) { + op->named.name = node->name.integer; + } + *out_op = op; + } + + /* + * Put the Node in the "op" object that the parser uses, so we + * can get it again quickly when this scope is closed + */ + op->common.node = node; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_load2_end_op + * + * PARAMETERS: walk_state - Current state of the parse tree walk + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the loading of the namespace, + * both control methods and everything else. + * + ******************************************************************************/ + +acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) +{ + union acpi_parse_object *op; + acpi_status status = AE_OK; + acpi_object_type object_type; + struct acpi_namespace_node *node; + union acpi_parse_object *arg; + struct acpi_namespace_node *new_node; +#ifndef ACPI_NO_METHOD_EXECUTION + u32 i; + u8 region_space; +#endif + + ACPI_FUNCTION_TRACE(ds_load2_end_op); + + op = walk_state->op; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", + walk_state->op_info->name, op, walk_state)); + + /* Check if opcode had an associated namespace object */ + + if (!(walk_state->op_info->flags & AML_NSOBJECT)) { +#ifndef ACPI_NO_METHOD_EXECUTION +#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE + /* No namespace object. Executable opcode? */ + + if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || + (walk_state->op_info->class == AML_CLASS_CONTROL)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "End/EXEC: %s (fl %8.8X)\n", + walk_state->op_info->name, + walk_state->op_info->flags)); + + /* Executing a type1 or type2 opcode outside of a method */ + + status = acpi_ds_exec_end_op(walk_state); + return_ACPI_STATUS(status); + } +#endif +#endif + return_ACPI_STATUS(AE_OK); + } + + if (op->common.aml_opcode == AML_SCOPE_OP) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Ending scope Op=%p State=%p\n", op, + walk_state)); + } + + object_type = walk_state->op_info->object_type; + + /* + * Get the Node/name from the earlier lookup + * (It was saved in the *op structure) + */ + node = op->common.node; + + /* + * Put the Node on the object stack (Contains the ACPI Name of + * this object) + */ + walk_state->operands[0] = (void *)node; + walk_state->num_operands = 1; + + /* Pop the scope stack */ + + if (acpi_ns_opens_scope(object_type) && + (op->common.aml_opcode != AML_INT_METHODCALL_OP)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "(%s) Popping scope for Op %p\n", + acpi_ut_get_type_name(object_type), op)); + + status = acpi_ds_scope_stack_pop(walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + } + + /* + * Named operations are as follows: + * + * AML_ALIAS + * AML_BANKFIELD + * AML_CREATEBITFIELD + * AML_CREATEBYTEFIELD + * AML_CREATEDWORDFIELD + * AML_CREATEFIELD + * AML_CREATEQWORDFIELD + * AML_CREATEWORDFIELD + * AML_DATA_REGION + * AML_DEVICE + * AML_EVENT + * AML_FIELD + * AML_INDEXFIELD + * AML_METHOD + * AML_METHODCALL + * AML_MUTEX + * AML_NAME + * AML_NAMEDFIELD + * AML_OPREGION + * AML_POWERRES + * AML_PROCESSOR + * AML_SCOPE + * AML_THERMALZONE + */ + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", + acpi_ps_get_opcode_name(op->common.aml_opcode), + walk_state, op, node)); + + /* Decode the opcode */ + + arg = op->common.value.arg; + + switch (walk_state->op_info->type) { +#ifndef ACPI_NO_METHOD_EXECUTION + + case AML_TYPE_CREATE_FIELD: + /* + * Create the field object, but the field buffer and index must + * be evaluated later during the execution phase + */ + status = acpi_ds_create_buffer_field(op, walk_state); + break; + + case AML_TYPE_NAMED_FIELD: + /* + * If we are executing a method, initialize the field + */ + if (walk_state->method_node) { + status = acpi_ds_init_field_objects(op, walk_state); + } + + switch (op->common.aml_opcode) { + case AML_INDEX_FIELD_OP: + + status = + acpi_ds_create_index_field(op, + (acpi_handle) arg-> + common.node, walk_state); + break; + + case AML_BANK_FIELD_OP: + + status = + acpi_ds_create_bank_field(op, arg->common.node, + walk_state); + break; + + case AML_FIELD_OP: + + status = + acpi_ds_create_field(op, arg->common.node, + walk_state); + break; + + default: + /* All NAMED_FIELD opcodes must be handled above */ + break; + } + break; + + case AML_TYPE_NAMED_SIMPLE: + + status = acpi_ds_create_operands(walk_state, arg); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + switch (op->common.aml_opcode) { + case AML_PROCESSOR_OP: + + status = acpi_ex_create_processor(walk_state); + break; + + case AML_POWER_RES_OP: + + status = acpi_ex_create_power_resource(walk_state); + break; + + case AML_MUTEX_OP: + + status = acpi_ex_create_mutex(walk_state); + break; + + case AML_EVENT_OP: + + status = acpi_ex_create_event(walk_state); + break; + + case AML_ALIAS_OP: + + status = acpi_ex_create_alias(walk_state); + break; + + default: + /* Unknown opcode */ + + status = AE_OK; + goto cleanup; + } + + /* Delete operands */ + + for (i = 1; i < walk_state->num_operands; i++) { + acpi_ut_remove_reference(walk_state->operands[i]); + walk_state->operands[i] = NULL; + } + + break; +#endif /* ACPI_NO_METHOD_EXECUTION */ + + case AML_TYPE_NAMED_COMPLEX: + + switch (op->common.aml_opcode) { +#ifndef ACPI_NO_METHOD_EXECUTION + case AML_REGION_OP: + case AML_DATA_REGION_OP: + + if (op->common.aml_opcode == AML_REGION_OP) { + region_space = (acpi_adr_space_type) + ((op->common.value.arg)->common.value. + integer); + } else { + region_space = REGION_DATA_TABLE; + } + + /* + * If we are executing a method, initialize the region + */ + if (walk_state->method_node) { + status = + acpi_ex_create_region(op->named.data, + op->named.length, + region_space, + walk_state); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + /* + * The op_region is not fully parsed at this time. Only valid + * argument is the space_id. (We must save the address of the + * AML of the address and length operands) + */ + + /* + * If we have a valid region, initialize it + * Namespace is NOT locked at this point. + */ + status = + acpi_ev_initialize_region + (acpi_ns_get_attached_object(node), FALSE); + if (ACPI_FAILURE(status)) { + /* + * If AE_NOT_EXIST is returned, it is not fatal + * because many regions get created before a handler + * is installed for said region. + */ + if (AE_NOT_EXIST == status) { + status = AE_OK; + } + } + break; + + case AML_NAME_OP: + + status = acpi_ds_create_node(walk_state, node, op); + break; + + case AML_METHOD_OP: + /* + * method_op pkg_length name_string method_flags term_list + * + * Note: We must create the method node/object pair as soon as we + * see the method declaration. This allows later pass1 parsing + * of invocations of the method (need to know the number of + * arguments.) + */ + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "LOADING-Method: State=%p Op=%p NamedObj=%p\n", + walk_state, op, op->named.node)); + + if (!acpi_ns_get_attached_object(op->named.node)) { + walk_state->operands[0] = + ACPI_CAST_PTR(void, op->named.node); + walk_state->num_operands = 1; + + status = + acpi_ds_create_operands(walk_state, + op->common.value. + arg); + if (ACPI_SUCCESS(status)) { + status = + acpi_ex_create_method(op->named. + data, + op->named. + length, + walk_state); + } + walk_state->operands[0] = NULL; + walk_state->num_operands = 0; + + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + break; + +#endif /* ACPI_NO_METHOD_EXECUTION */ + + default: + /* All NAMED_COMPLEX opcodes must be handled above */ + break; + } + break; + + case AML_CLASS_INTERNAL: + + /* case AML_INT_NAMEPATH_OP: */ + break; + + case AML_CLASS_METHOD_CALL: + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", + walk_state, op, node)); + + /* + * Lookup the method name and save the Node + */ + status = + acpi_ns_lookup(walk_state->scope_info, + arg->common.value.string, ACPI_TYPE_ANY, + ACPI_IMODE_LOAD_PASS2, + ACPI_NS_SEARCH_PARENT | + ACPI_NS_DONT_OPEN_SCOPE, walk_state, + &(new_node)); + if (ACPI_SUCCESS(status)) { + /* + * Make sure that what we found is indeed a method + * We didn't search for a method on purpose, to see if the name + * would resolve + */ + if (new_node->type != ACPI_TYPE_METHOD) { + status = AE_AML_OPERAND_TYPE; + } + + /* We could put the returned object (Node) on the object stack for + * later, but for now, we will put it in the "op" object that the + * parser uses, so we can get it again at the end of this scope + */ + op->common.node = new_node; + } else { + ACPI_ERROR_NAMESPACE(arg->common.value.string, status); + } + break; + + default: + break; + } + + cleanup: + + /* Remove the Node pushed at the very beginning */ + + walk_state->operands[0] = NULL; + walk_state->num_operands = 0; + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c new file mode 100644 index 000000000000..8030541a49f7 --- /dev/null +++ b/drivers/acpi/acpica/dswscope.c @@ -0,0 +1,214 @@ +/****************************************************************************** + * + * Module Name: dswscope - Scope stack manipulation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dswscope") + +/**************************************************************************** + * + * FUNCTION: acpi_ds_scope_stack_clear + * + * PARAMETERS: walk_state - Current state + * + * RETURN: None + * + * DESCRIPTION: Pop (and free) everything on the scope stack except the + * root scope object (which remains at the stack top.) + * + ***************************************************************************/ +void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state) +{ + union acpi_generic_state *scope_info; + + ACPI_FUNCTION_NAME(ds_scope_stack_clear); + + while (walk_state->scope_info) { + + /* Pop a scope off the stack */ + + scope_info = walk_state->scope_info; + walk_state->scope_info = scope_info->scope.next; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Popped object type (%s)\n", + acpi_ut_get_type_name(scope_info->common. + value))); + acpi_ut_delete_generic_state(scope_info); + } +} + +/**************************************************************************** + * + * FUNCTION: acpi_ds_scope_stack_push + * + * PARAMETERS: Node - Name to be made current + * Type - Type of frame being pushed + * walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Push the current scope on the scope stack, and make the + * passed Node current. + * + ***************************************************************************/ + +acpi_status +acpi_ds_scope_stack_push(struct acpi_namespace_node *node, + acpi_object_type type, + struct acpi_walk_state *walk_state) +{ + union acpi_generic_state *scope_info; + union acpi_generic_state *old_scope_info; + + ACPI_FUNCTION_TRACE(ds_scope_stack_push); + + if (!node) { + + /* Invalid scope */ + + ACPI_ERROR((AE_INFO, "Null scope parameter")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Make sure object type is valid */ + + if (!acpi_ut_valid_object_type(type)) { + ACPI_WARNING((AE_INFO, "Invalid object type: 0x%X", type)); + } + + /* Allocate a new scope object */ + + scope_info = acpi_ut_create_generic_state(); + if (!scope_info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Init new scope object */ + + scope_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_WSCOPE; + scope_info->scope.node = node; + scope_info->common.value = (u16) type; + + walk_state->scope_depth++; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[%.2d] Pushed scope ", + (u32) walk_state->scope_depth)); + + old_scope_info = walk_state->scope_info; + if (old_scope_info) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, + "[%4.4s] (%s)", + acpi_ut_get_node_name(old_scope_info-> + scope.node), + acpi_ut_get_type_name(old_scope_info-> + common.value))); + } else { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (%s)", "ROOT")); + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, + ", New scope -> [%4.4s] (%s)\n", + acpi_ut_get_node_name(scope_info->scope.node), + acpi_ut_get_type_name(scope_info->common.value))); + + /* Push new scope object onto stack */ + + acpi_ut_push_generic_state(&walk_state->scope_info, scope_info); + return_ACPI_STATUS(AE_OK); +} + +/**************************************************************************** + * + * FUNCTION: acpi_ds_scope_stack_pop + * + * PARAMETERS: walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Pop the scope stack once. + * + ***************************************************************************/ + +acpi_status acpi_ds_scope_stack_pop(struct acpi_walk_state *walk_state) +{ + union acpi_generic_state *scope_info; + union acpi_generic_state *new_scope_info; + + ACPI_FUNCTION_TRACE(ds_scope_stack_pop); + + /* + * Pop scope info object off the stack. + */ + scope_info = acpi_ut_pop_generic_state(&walk_state->scope_info); + if (!scope_info) { + return_ACPI_STATUS(AE_STACK_UNDERFLOW); + } + + walk_state->scope_depth--; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[%.2d] Popped scope [%4.4s] (%s), New scope -> ", + (u32) walk_state->scope_depth, + acpi_ut_get_node_name(scope_info->scope.node), + acpi_ut_get_type_name(scope_info->common.value))); + + new_scope_info = walk_state->scope_info; + if (new_scope_info) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, + "[%4.4s] (%s)\n", + acpi_ut_get_node_name(new_scope_info-> + scope.node), + acpi_ut_get_type_name(new_scope_info-> + common.value))); + } else { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (ROOT)\n")); + } + + acpi_ut_delete_generic_state(scope_info); + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c new file mode 100644 index 000000000000..a7543c43c151 --- /dev/null +++ b/drivers/acpi/acpica/dswstate.c @@ -0,0 +1,753 @@ +/****************************************************************************** + * + * Module Name: dswstate - Dispatcher parse tree walk management routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dswstate") + + /* Local prototypes */ +static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws); +static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws); + +/******************************************************************************* + * + * FUNCTION: acpi_ds_result_pop + * + * PARAMETERS: Object - Where to return the popped object + * walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop an object off the top of this walk's result stack + * + ******************************************************************************/ + +acpi_status +acpi_ds_result_pop(union acpi_operand_object **object, + struct acpi_walk_state *walk_state) +{ + u32 index; + union acpi_generic_state *state; + acpi_status status; + + ACPI_FUNCTION_NAME(ds_result_pop); + + state = walk_state->results; + + /* Incorrect state of result stack */ + + if (state && !walk_state->result_count) { + ACPI_ERROR((AE_INFO, "No results on result stack")); + return (AE_AML_INTERNAL); + } + + if (!state && walk_state->result_count) { + ACPI_ERROR((AE_INFO, "No result state for result stack")); + return (AE_AML_INTERNAL); + } + + /* Empty result stack */ + + if (!state) { + ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", + walk_state)); + return (AE_AML_NO_RETURN_VALUE); + } + + /* Return object of the top element and clean that top element result stack */ + + walk_state->result_count--; + index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; + + *object = state->results.obj_desc[index]; + if (!*object) { + ACPI_ERROR((AE_INFO, + "No result objects on result stack, State=%p", + walk_state)); + return (AE_AML_NO_RETURN_VALUE); + } + + state->results.obj_desc[index] = NULL; + if (index == 0) { + status = acpi_ds_result_stack_pop(walk_state); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, + acpi_ut_get_object_type_name(*object), + index, walk_state, walk_state->result_count)); + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_result_push + * + * PARAMETERS: Object - Where to return the popped object + * walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Push an object onto the current result stack + * + ******************************************************************************/ + +acpi_status +acpi_ds_result_push(union acpi_operand_object * object, + struct acpi_walk_state * walk_state) +{ + union acpi_generic_state *state; + acpi_status status; + u32 index; + + ACPI_FUNCTION_NAME(ds_result_push); + + if (walk_state->result_count > walk_state->result_size) { + ACPI_ERROR((AE_INFO, "Result stack is full")); + return (AE_AML_INTERNAL); + } else if (walk_state->result_count == walk_state->result_size) { + + /* Extend the result stack */ + + status = acpi_ds_result_stack_push(walk_state); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Failed to extend the result stack")); + return (status); + } + } + + if (!(walk_state->result_count < walk_state->result_size)) { + ACPI_ERROR((AE_INFO, "No free elements in result stack")); + return (AE_AML_INTERNAL); + } + + state = walk_state->results; + if (!state) { + ACPI_ERROR((AE_INFO, "No result stack frame during push")); + return (AE_AML_INTERNAL); + } + + if (!object) { + ACPI_ERROR((AE_INFO, + "Null Object! Obj=%p State=%p Num=%X", + object, walk_state, walk_state->result_count)); + return (AE_BAD_PARAMETER); + } + + /* Assign the address of object to the top free element of result stack */ + + index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; + state->results.obj_desc[index] = object; + walk_state->result_count++; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", + object, + acpi_ut_get_object_type_name((union + acpi_operand_object *) + object), walk_state, + walk_state->result_count, + walk_state->current_result)); + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_result_stack_push + * + * PARAMETERS: walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Push an object onto the walk_state result stack + * + ******************************************************************************/ + +static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state) +{ + union acpi_generic_state *state; + + ACPI_FUNCTION_NAME(ds_result_stack_push); + + /* Check for stack overflow */ + + if (((u32) walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) > + ACPI_RESULTS_OBJ_NUM_MAX) { + ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%X", + walk_state, walk_state->result_size)); + return (AE_STACK_OVERFLOW); + } + + state = acpi_ut_create_generic_state(); + if (!state) { + return (AE_NO_MEMORY); + } + + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT; + acpi_ut_push_generic_state(&walk_state->results, state); + + /* Increase the length of the result stack by the length of frame */ + + walk_state->result_size += ACPI_RESULTS_FRAME_OBJ_NUM; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n", + state, walk_state)); + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_result_stack_pop + * + * PARAMETERS: walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop an object off of the walk_state result stack + * + ******************************************************************************/ + +static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state) +{ + union acpi_generic_state *state; + + ACPI_FUNCTION_NAME(ds_result_stack_pop); + + /* Check for stack underflow */ + + if (walk_state->results == NULL) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Result stack underflow - State=%p\n", + walk_state)); + return (AE_AML_NO_OPERAND); + } + + if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) { + ACPI_ERROR((AE_INFO, "Insufficient result stack size")); + return (AE_AML_INTERNAL); + } + + state = acpi_ut_pop_generic_state(&walk_state->results); + acpi_ut_delete_generic_state(state); + + /* Decrease the length of result stack by the length of frame */ + + walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Result=%p RemainingResults=%X State=%p\n", + state, walk_state->result_count, walk_state)); + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_obj_stack_push + * + * PARAMETERS: Object - Object to push + * walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Push an object onto this walk's object/operand stack + * + ******************************************************************************/ + +acpi_status +acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) +{ + ACPI_FUNCTION_NAME(ds_obj_stack_push); + + /* Check for stack overflow */ + + if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) { + ACPI_ERROR((AE_INFO, + "Object stack overflow! Obj=%p State=%p #Ops=%X", + object, walk_state, walk_state->num_operands)); + return (AE_STACK_OVERFLOW); + } + + /* Put the object onto the stack */ + + walk_state->operands[walk_state->operand_index] = object; + walk_state->num_operands++; + + /* For the usual order of filling the operand stack */ + + walk_state->operand_index++; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", + object, + acpi_ut_get_object_type_name((union + acpi_operand_object *) + object), walk_state, + walk_state->num_operands)); + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_obj_stack_pop + * + * PARAMETERS: pop_count - Number of objects/entries to pop + * walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT + * deleted by this routine. + * + ******************************************************************************/ + +acpi_status +acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state) +{ + u32 i; + + ACPI_FUNCTION_NAME(ds_obj_stack_pop); + + for (i = 0; i < pop_count; i++) { + + /* Check for stack underflow */ + + if (walk_state->num_operands == 0) { + ACPI_ERROR((AE_INFO, + "Object stack underflow! Count=%X State=%p #Ops=%X", + pop_count, walk_state, + walk_state->num_operands)); + return (AE_STACK_UNDERFLOW); + } + + /* Just set the stack entry to null */ + + walk_state->num_operands--; + walk_state->operands[walk_state->num_operands] = NULL; + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", + pop_count, walk_state, walk_state->num_operands)); + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_obj_stack_pop_and_delete + * + * PARAMETERS: pop_count - Number of objects/entries to pop + * walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop this walk's object stack and delete each object that is + * popped off. + * + ******************************************************************************/ + +void +acpi_ds_obj_stack_pop_and_delete(u32 pop_count, + struct acpi_walk_state *walk_state) +{ + s32 i; + union acpi_operand_object *obj_desc; + + ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); + + if (pop_count == 0) { + return; + } + + for (i = (s32) pop_count - 1; i >= 0; i--) { + if (walk_state->num_operands == 0) { + return; + } + + /* Pop the stack and delete an object if present in this stack entry */ + + walk_state->num_operands--; + obj_desc = walk_state->operands[i]; + if (obj_desc) { + acpi_ut_remove_reference(walk_state->operands[i]); + walk_state->operands[i] = NULL; + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", + pop_count, walk_state, walk_state->num_operands)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_get_current_walk_state + * + * PARAMETERS: Thread - Get current active state for this Thread + * + * RETURN: Pointer to the current walk state + * + * DESCRIPTION: Get the walk state that is at the head of the list (the "current" + * walk state.) + * + ******************************************************************************/ + +struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state + *thread) +{ + ACPI_FUNCTION_NAME(ds_get_current_walk_state); + + if (!thread) { + return (NULL); + } + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current WalkState %p\n", + thread->walk_state_list)); + + return (thread->walk_state_list); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_push_walk_state + * + * PARAMETERS: walk_state - State to push + * Thread - Thread state object + * + * RETURN: None + * + * DESCRIPTION: Place the Thread state at the head of the state list + * + ******************************************************************************/ + +void +acpi_ds_push_walk_state(struct acpi_walk_state *walk_state, + struct acpi_thread_state *thread) +{ + ACPI_FUNCTION_TRACE(ds_push_walk_state); + + walk_state->next = thread->walk_state_list; + thread->walk_state_list = walk_state; + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_pop_walk_state + * + * PARAMETERS: Thread - Current thread state + * + * RETURN: A walk_state object popped from the thread's stack + * + * DESCRIPTION: Remove and return the walkstate object that is at the head of + * the walk stack for the given walk list. NULL indicates that + * the list is empty. + * + ******************************************************************************/ + +struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) +{ + struct acpi_walk_state *walk_state; + + ACPI_FUNCTION_TRACE(ds_pop_walk_state); + + walk_state = thread->walk_state_list; + + if (walk_state) { + + /* Next walk state becomes the current walk state */ + + thread->walk_state_list = walk_state->next; + + /* + * Don't clear the NEXT field, this serves as an indicator + * that there is a parent WALK STATE + * Do Not: walk_state->Next = NULL; + */ + } + + return_PTR(walk_state); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_create_walk_state + * + * PARAMETERS: owner_id - ID for object creation + * Origin - Starting point for this walk + * method_desc - Method object + * Thread - Current thread state + * + * RETURN: Pointer to the new walk state. + * + * DESCRIPTION: Allocate and initialize a new walk state. The current walk + * state is set to this new state. + * + ******************************************************************************/ + +struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object + *origin, union acpi_operand_object + *method_desc, struct acpi_thread_state + *thread) +{ + struct acpi_walk_state *walk_state; + + ACPI_FUNCTION_TRACE(ds_create_walk_state); + + walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state)); + if (!walk_state) { + return_PTR(NULL); + } + + walk_state->descriptor_type = ACPI_DESC_TYPE_WALK; + walk_state->method_desc = method_desc; + walk_state->owner_id = owner_id; + walk_state->origin = origin; + walk_state->thread = thread; + + walk_state->parser_state.start_op = origin; + + /* Init the method args/local */ + +#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) + acpi_ds_method_data_init(walk_state); +#endif + + /* Put the new state at the head of the walk list */ + + if (thread) { + acpi_ds_push_walk_state(walk_state, thread); + } + + return_PTR(walk_state); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_init_aml_walk + * + * PARAMETERS: walk_state - New state to be initialized + * Op - Current parse op + * method_node - Control method NS node, if any + * aml_start - Start of AML + * aml_length - Length of AML + * Info - Method info block (params, etc.) + * pass_number - 1, 2, or 3 + * + * RETURN: Status + * + * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk + * + ******************************************************************************/ + +acpi_status +acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, + struct acpi_namespace_node *method_node, + u8 * aml_start, + u32 aml_length, + struct acpi_evaluate_info *info, u8 pass_number) +{ + acpi_status status; + struct acpi_parse_state *parser_state = &walk_state->parser_state; + union acpi_parse_object *extra_op; + + ACPI_FUNCTION_TRACE(ds_init_aml_walk); + + walk_state->parser_state.aml = + walk_state->parser_state.aml_start = aml_start; + walk_state->parser_state.aml_end = + walk_state->parser_state.pkg_end = aml_start + aml_length; + + /* The next_op of the next_walk will be the beginning of the method */ + + walk_state->next_op = NULL; + walk_state->pass_number = pass_number; + + if (info) { + walk_state->params = info->parameters; + walk_state->caller_return_desc = &info->return_object; + } + + status = acpi_ps_init_scope(&walk_state->parser_state, op); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (method_node) { + walk_state->parser_state.start_node = method_node; + walk_state->walk_type = ACPI_WALK_METHOD; + walk_state->method_node = method_node; + walk_state->method_desc = + acpi_ns_get_attached_object(method_node); + + /* Push start scope on scope stack and make it current */ + + status = + acpi_ds_scope_stack_push(method_node, ACPI_TYPE_METHOD, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Init the method arguments */ + + status = acpi_ds_method_data_init_args(walk_state->params, + ACPI_METHOD_NUM_ARGS, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } else { + /* + * Setup the current scope. + * Find a Named Op that has a namespace node associated with it. + * search upwards from this Op. Current scope is the first + * Op with a namespace node. + */ + extra_op = parser_state->start_op; + while (extra_op && !extra_op->common.node) { + extra_op = extra_op->common.parent; + } + + if (!extra_op) { + parser_state->start_node = NULL; + } else { + parser_state->start_node = extra_op->common.node; + } + + if (parser_state->start_node) { + + /* Push start scope on scope stack and make it current */ + + status = + acpi_ds_scope_stack_push(parser_state->start_node, + parser_state->start_node-> + type, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + } + + status = acpi_ds_init_callbacks(walk_state, pass_number); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_delete_walk_state + * + * PARAMETERS: walk_state - State to delete + * + * RETURN: Status + * + * DESCRIPTION: Delete a walk state including all internal data structures + * + ******************************************************************************/ + +void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) +{ + union acpi_generic_state *state; + + ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state); + + if (!walk_state) { + return; + } + + if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) { + ACPI_ERROR((AE_INFO, "%p is not a valid walk state", + walk_state)); + return; + } + + /* There should not be any open scopes */ + + if (walk_state->parser_state.scope) { + ACPI_ERROR((AE_INFO, "%p walk still has a scope list", + walk_state)); + acpi_ps_cleanup_scope(&walk_state->parser_state); + } + + /* Always must free any linked control states */ + + while (walk_state->control_state) { + state = walk_state->control_state; + walk_state->control_state = state->common.next; + + acpi_ut_delete_generic_state(state); + } + + /* Always must free any linked parse states */ + + while (walk_state->scope_info) { + state = walk_state->scope_info; + walk_state->scope_info = state->common.next; + + acpi_ut_delete_generic_state(state); + } + + /* Always must free any stacked result states */ + + while (walk_state->results) { + state = walk_state->results; + walk_state->results = state->common.next; + + acpi_ut_delete_generic_state(state); + } + + ACPI_FREE(walk_state); + return_VOID; +} diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c new file mode 100644 index 000000000000..86bf08365dad --- /dev/null +++ b/drivers/acpi/acpica/evevent.c @@ -0,0 +1,313 @@ +/****************************************************************************** + * + * Module Name: evevent - Fixed Event handling and dispatch + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evevent") + +/* Local prototypes */ +static acpi_status acpi_ev_fixed_event_initialize(void); + +static u32 acpi_ev_fixed_event_dispatch(u32 event); + +/******************************************************************************* + * + * FUNCTION: acpi_ev_initialize_events + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE) + * + ******************************************************************************/ + +acpi_status acpi_ev_initialize_events(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_initialize_events); + + /* + * Initialize the Fixed and General Purpose Events. This is done prior to + * enabling SCIs to prevent interrupts from occurring before the handlers + * are installed. + */ + status = acpi_ev_fixed_event_initialize(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to initialize fixed events")); + return_ACPI_STATUS(status); + } + + status = acpi_ev_gpe_initialize(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to initialize general purpose events")); + return_ACPI_STATUS(status); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_fadt_gpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Completes initialization of the FADT-defined GPE blocks + * (0 and 1). This causes the _PRW methods to be run, so the HW + * must be fully initialized at this point, including global lock + * support. + * + ******************************************************************************/ + +acpi_status acpi_ev_install_fadt_gpes(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_install_fadt_gpes); + + /* Namespace must be locked */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* FADT GPE Block 0 */ + + (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device, + acpi_gbl_gpe_fadt_blocks[0]); + + /* FADT GPE Block 1 */ + + (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device, + acpi_gbl_gpe_fadt_blocks[1]); + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_xrupt_handlers + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock + * + ******************************************************************************/ + +acpi_status acpi_ev_install_xrupt_handlers(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers); + + /* Install the SCI handler */ + + status = acpi_ev_install_sci_handler(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to install System Control Interrupt handler")); + return_ACPI_STATUS(status); + } + + /* Install the handler for the Global Lock */ + + status = acpi_ev_init_global_lock_handler(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to initialize Global Lock handler")); + return_ACPI_STATUS(status); + } + + acpi_gbl_events_initialized = TRUE; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_fixed_event_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Install the fixed event handlers and enable the fixed events. + * + ******************************************************************************/ + +static acpi_status acpi_ev_fixed_event_initialize(void) +{ + u32 i; + acpi_status status; + + /* + * Initialize the structure that keeps track of fixed event handlers and + * enable the fixed events. + */ + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + acpi_gbl_fixed_event_handlers[i].handler = NULL; + acpi_gbl_fixed_event_handlers[i].context = NULL; + + /* Enable the fixed event */ + + if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) { + status = + acpi_set_register(acpi_gbl_fixed_event_info[i]. + enable_register_id, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + } + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_fixed_event_detect + * + * PARAMETERS: None + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Checks the PM status register for active fixed events + * + ******************************************************************************/ + +u32 acpi_ev_fixed_event_detect(void) +{ + u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; + u32 fixed_status; + u32 fixed_enable; + u32 i; + + ACPI_FUNCTION_NAME(ev_fixed_event_detect); + + /* + * Read the fixed feature status and enable registers, as all the cases + * depend on their values. Ignore errors here. + */ + (void)acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status); + (void)acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable); + + ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, + "Fixed Event Block: Enable %08X Status %08X\n", + fixed_enable, fixed_status)); + + /* + * Check for all possible Fixed Events and dispatch those that are active + */ + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + + /* Both the status and enable bits must be on for this event */ + + if ((fixed_status & acpi_gbl_fixed_event_info[i]. + status_bit_mask) + && (fixed_enable & acpi_gbl_fixed_event_info[i]. + enable_bit_mask)) { + + /* Found an active (signalled) event */ + acpi_os_fixed_event_count(i); + int_status |= acpi_ev_fixed_event_dispatch(i); + } + } + + return (int_status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_fixed_event_dispatch + * + * PARAMETERS: Event - Event type + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Clears the status bit for the requested event, calls the + * handler that previously registered for the event. + * + ******************************************************************************/ + +static u32 acpi_ev_fixed_event_dispatch(u32 event) +{ + + ACPI_FUNCTION_ENTRY(); + + /* Clear the status bit */ + + (void)acpi_set_register(acpi_gbl_fixed_event_info[event]. + status_register_id, 1); + + /* + * Make sure we've got a handler. If not, report an error. The event is + * disabled to prevent further interrupts. + */ + if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { + (void)acpi_set_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, 0); + + ACPI_ERROR((AE_INFO, + "No installed handler for fixed event [%08X]", + event)); + + return (ACPI_INTERRUPT_NOT_HANDLED); + } + + /* Invoke the Fixed Event handler */ + + return ((acpi_gbl_fixed_event_handlers[event]. + handler) (acpi_gbl_fixed_event_handlers[event].context)); +} diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c new file mode 100644 index 000000000000..d9779608dbd7 --- /dev/null +++ b/drivers/acpi/acpica/evgpe.c @@ -0,0 +1,722 @@ +/****************************************************************************** + * + * Module Name: evgpe - General Purpose Event handling and dispatch + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evgpe") + +/* Local prototypes */ +static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context); + +/******************************************************************************* + * + * FUNCTION: acpi_ev_set_gpe_type + * + * PARAMETERS: gpe_event_info - GPE to set + * Type - New type + * + * RETURN: Status + * + * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run) + * + ******************************************************************************/ + +acpi_status +acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_set_gpe_type); + + /* Validate type and update register enable masks */ + + switch (type) { + case ACPI_GPE_TYPE_WAKE: + case ACPI_GPE_TYPE_RUNTIME: + case ACPI_GPE_TYPE_WAKE_RUN: + break; + + default: + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Disable the GPE if currently enabled */ + + status = acpi_ev_disable_gpe(gpe_event_info); + + /* Type was validated above */ + + gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */ + gpe_event_info->flags |= type; /* Insert type */ + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_update_gpe_enable_masks + * + * PARAMETERS: gpe_event_info - GPE to update + * Type - What to do: ACPI_GPE_DISABLE or + * ACPI_GPE_ENABLE + * + * RETURN: Status + * + * DESCRIPTION: Updates GPE register enable masks based on the GPE type + * + ******************************************************************************/ + +acpi_status +acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, + u8 type) +{ + struct acpi_gpe_register_info *gpe_register_info; + u8 register_bit; + + ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks); + + gpe_register_info = gpe_event_info->register_info; + if (!gpe_register_info) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + register_bit = (u8) + (1 << + (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); + + /* 1) Disable case. Simply clear all enable bits */ + + if (type == ACPI_GPE_DISABLE) { + ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, + register_bit); + ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit); + return_ACPI_STATUS(AE_OK); + } + + /* 2) Enable case. Set/Clear the appropriate enable bits */ + + switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { + case ACPI_GPE_TYPE_WAKE: + ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit); + ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit); + break; + + case ACPI_GPE_TYPE_RUNTIME: + ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, + register_bit); + ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit); + break; + + case ACPI_GPE_TYPE_WAKE_RUN: + ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit); + ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit); + break; + + default: + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_enable_gpe + * + * PARAMETERS: gpe_event_info - GPE to enable + * write_to_hardware - Enable now, or just mark data structs + * (WAKE GPEs should be deferred) + * + * RETURN: Status + * + * DESCRIPTION: Enable a GPE based on the GPE type + * + ******************************************************************************/ + +acpi_status +acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info, + u8 write_to_hardware) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_enable_gpe); + + /* Make sure HW enable masks are updated */ + + status = + acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_ENABLE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Mark wake-enabled or HW enable, or both */ + + switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { + case ACPI_GPE_TYPE_WAKE: + + ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); + break; + + case ACPI_GPE_TYPE_WAKE_RUN: + + ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); + + /*lint -fallthrough */ + + case ACPI_GPE_TYPE_RUNTIME: + + ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); + + if (write_to_hardware) { + + /* Clear the GPE (of stale events), then enable it */ + + status = acpi_hw_clear_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Enable the requested runtime GPE */ + + status = acpi_hw_write_gpe_enable_reg(gpe_event_info); + } + break; + + default: + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_disable_gpe + * + * PARAMETERS: gpe_event_info - GPE to disable + * + * RETURN: Status + * + * DESCRIPTION: Disable a GPE based on the GPE type + * + ******************************************************************************/ + +acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_disable_gpe); + + /* Make sure HW enable masks are updated */ + + status = + acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_DISABLE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Clear the appropriate enabled flags for this GPE */ + + switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { + case ACPI_GPE_TYPE_WAKE: + ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); + break; + + case ACPI_GPE_TYPE_WAKE_RUN: + ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); + + /* fallthrough */ + + case ACPI_GPE_TYPE_RUNTIME: + + /* Disable the requested runtime GPE */ + + ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); + break; + + default: + break; + } + + /* + * Even if we don't know the GPE type, make sure that we always + * disable it. low_disable_gpe will just clear the enable bit for this + * GPE and write it. It will not write out the current GPE enable mask, + * since this may inadvertently enable GPEs too early, if a rogue GPE has + * come in during ACPICA initialization - possibly as a result of AML or + * other code that has enabled the GPE. + */ + status = acpi_hw_low_disable_gpe(gpe_event_info); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_get_gpe_event_info + * + * PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1 + * gpe_number - Raw GPE number + * + * RETURN: A GPE event_info struct. NULL if not a valid GPE + * + * DESCRIPTION: Returns the event_info struct associated with this GPE. + * Validates the gpe_block and the gpe_number + * + * Should be called only when the GPE lists are semaphore locked + * and not subject to change. + * + ******************************************************************************/ + +struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, + u32 gpe_number) +{ + union acpi_operand_object *obj_desc; + struct acpi_gpe_block_info *gpe_block; + u32 i; + + ACPI_FUNCTION_ENTRY(); + + /* A NULL gpe_block means use the FADT-defined GPE block(s) */ + + if (!gpe_device) { + + /* Examine GPE Block 0 and 1 (These blocks are permanent) */ + + for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) { + gpe_block = acpi_gbl_gpe_fadt_blocks[i]; + if (gpe_block) { + if ((gpe_number >= gpe_block->block_base_number) + && (gpe_number < + gpe_block->block_base_number + + (gpe_block->register_count * 8))) { + return (&gpe_block-> + event_info[gpe_number - + gpe_block-> + block_base_number]); + } + } + } + + /* The gpe_number was not in the range of either FADT GPE block */ + + return (NULL); + } + + /* A Non-NULL gpe_device means this is a GPE Block Device */ + + obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *) + gpe_device); + if (!obj_desc || !obj_desc->device.gpe_block) { + return (NULL); + } + + gpe_block = obj_desc->device.gpe_block; + + if ((gpe_number >= gpe_block->block_base_number) && + (gpe_number < + gpe_block->block_base_number + (gpe_block->register_count * 8))) { + return (&gpe_block-> + event_info[gpe_number - gpe_block->block_base_number]); + } + + return (NULL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_gpe_detect + * + * PARAMETERS: gpe_xrupt_list - Interrupt block for this interrupt. + * Can have multiple GPE blocks attached. + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Detect if any GP events have occurred. This function is + * executed at interrupt level. + * + ******************************************************************************/ + +u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) +{ + acpi_status status; + struct acpi_gpe_block_info *gpe_block; + struct acpi_gpe_register_info *gpe_register_info; + u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; + u8 enabled_status_byte; + u32 status_reg; + u32 enable_reg; + acpi_cpu_flags flags; + u32 i; + u32 j; + + ACPI_FUNCTION_NAME(ev_gpe_detect); + + /* Check for the case where there are no GPEs */ + + if (!gpe_xrupt_list) { + return (int_status); + } + + /* + * We need to obtain the GPE lock for both the data structs and registers + * Note: Not necessary to obtain the hardware lock, since the GPE + * registers are owned by the gpe_lock. + */ + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Examine all GPE blocks attached to this interrupt level */ + + gpe_block = gpe_xrupt_list->gpe_block_list_head; + while (gpe_block) { + /* + * Read all of the 8-bit GPE status and enable registers in this GPE + * block, saving all of them. Find all currently active GP events. + */ + for (i = 0; i < gpe_block->register_count; i++) { + + /* Get the next status/enable pair */ + + gpe_register_info = &gpe_block->register_info[i]; + + /* Read the Status Register */ + + status = + acpi_read(&status_reg, + &gpe_register_info->status_address); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* Read the Enable Register */ + + status = + acpi_read(&enable_reg, + &gpe_register_info->enable_address); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, + "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n", + gpe_register_info->base_gpe_number, + status_reg, enable_reg)); + + /* Check if there is anything active at all in this register */ + + enabled_status_byte = (u8) (status_reg & enable_reg); + if (!enabled_status_byte) { + + /* No active GPEs in this register, move on */ + + continue; + } + + /* Now look at the individual GPEs in this byte register */ + + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { + + /* Examine one GPE bit */ + + if (enabled_status_byte & (1 << j)) { + /* + * Found an active GPE. Dispatch the event to a handler + * or method. + */ + int_status |= + acpi_ev_gpe_dispatch(&gpe_block-> + event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number); + } + } + } + + gpe_block = gpe_block->next; + } + + unlock_and_exit: + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + return (int_status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_asynch_execute_gpe_method + * + * PARAMETERS: Context (gpe_event_info) - Info for this GPE + * + * RETURN: None + * + * DESCRIPTION: Perform the actual execution of a GPE control method. This + * function is called from an invocation of acpi_os_execute and + * therefore does NOT execute at interrupt level - so that + * the control method itself is not executed in the context of + * an interrupt handler. + * + ******************************************************************************/ +static void acpi_ev_asynch_enable_gpe(void *context); + +static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) +{ + struct acpi_gpe_event_info *gpe_event_info = (void *)context; + acpi_status status; + struct acpi_gpe_event_info local_gpe_event_info; + struct acpi_evaluate_info *info; + + ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_VOID; + } + + /* Must revalidate the gpe_number/gpe_block */ + + if (!acpi_ev_valid_gpe_event(gpe_event_info)) { + status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_VOID; + } + + /* Set the GPE flags for return to enabled state */ + + (void)acpi_ev_enable_gpe(gpe_event_info, FALSE); + + /* + * Take a snapshot of the GPE info for this level - we copy the info to + * prevent a race condition with remove_handler/remove_block. + */ + ACPI_MEMCPY(&local_gpe_event_info, gpe_event_info, + sizeof(struct acpi_gpe_event_info)); + + status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_VOID; + } + + /* + * Must check for control method type dispatch one more time to avoid a + * race with ev_gpe_install_handler + */ + if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_METHOD) { + + /* Allocate the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + status = AE_NO_MEMORY; + } else { + /* + * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx + * control method that corresponds to this GPE + */ + info->prefix_node = + local_gpe_event_info.dispatch.method_node; + info->flags = ACPI_IGNORE_RETURN_VALUE; + + status = acpi_ns_evaluate(info); + ACPI_FREE(info); + } + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "while evaluating GPE method [%4.4s]", + acpi_ut_get_node_name + (local_gpe_event_info.dispatch. + method_node))); + } + } + /* Defer enabling of GPE until all notify handlers are done */ + acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe, + gpe_event_info); + return_VOID; +} + +static void acpi_ev_asynch_enable_gpe(void *context) +{ + struct acpi_gpe_event_info *gpe_event_info = context; + acpi_status status; + if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == + ACPI_GPE_LEVEL_TRIGGERED) { + /* + * GPE is level-triggered, we clear the GPE status bit after handling + * the event. + */ + status = acpi_hw_clear_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + return_VOID; + } + } + + /* Enable this GPE */ + (void)acpi_hw_write_gpe_enable_reg(gpe_event_info); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_gpe_dispatch + * + * PARAMETERS: gpe_event_info - Info for this GPE + * gpe_number - Number relative to the parent GPE block + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) + * or method (e.g. _Lxx/_Exx) handler. + * + * This function executes at interrupt level. + * + ******************************************************************************/ + +u32 +acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_gpe_dispatch); + + acpi_os_gpe_count(gpe_number); + + /* + * If edge-triggered, clear the GPE status bit now. Note that + * level-triggered events are cleared after the GPE is serviced. + */ + if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == + ACPI_GPE_EDGE_TRIGGERED) { + status = acpi_hw_clear_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to clear GPE[%2X]", + gpe_number)); + return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); + } + } + + /* + * Dispatch the GPE to either an installed handler, or the control method + * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke + * it and do not attempt to run the method. If there is neither a handler + * nor a method, we disable this GPE to prevent further such pointless + * events from firing. + */ + switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { + case ACPI_GPE_DISPATCH_HANDLER: + + /* + * Invoke the installed handler (at interrupt level) + * Ignore return status for now. + * TBD: leave GPE disabled on error? + */ + (void)gpe_event_info->dispatch.handler->address(gpe_event_info-> + dispatch. + handler-> + context); + + /* It is now safe to clear level-triggered events. */ + + if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == + ACPI_GPE_LEVEL_TRIGGERED) { + status = acpi_hw_clear_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to clear GPE[%2X]", + gpe_number)); + return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); + } + } + break; + + case ACPI_GPE_DISPATCH_METHOD: + + /* + * Disable the GPE, so it doesn't keep firing before the method has a + * chance to run (it runs asynchronously with interrupts enabled). + */ + status = acpi_ev_disable_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to disable GPE[%2X]", + gpe_number)); + return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); + } + + /* + * Execute the method associated with the GPE + * NOTE: Level-triggered GPEs are cleared after the method completes. + */ + status = acpi_os_execute(OSL_GPE_HANDLER, + acpi_ev_asynch_execute_gpe_method, + gpe_event_info); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to queue handler for GPE[%2X] - event disabled", + gpe_number)); + } + break; + + default: + + /* No handler or method to run! */ + + ACPI_ERROR((AE_INFO, + "No handler or method for GPE[%2X], disabling event", + gpe_number)); + + /* + * Disable the GPE. The GPE will remain disabled until the ACPICA + * Core Subsystem is restarted, or a handler is installed. + */ + status = acpi_ev_disable_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to disable GPE[%2X]", + gpe_number)); + return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); + } + break; + } + + return_UINT32(ACPI_INTERRUPT_HANDLED); +} diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c new file mode 100644 index 000000000000..2a8d1856038f --- /dev/null +++ b/drivers/acpi/acpica/evgpeblk.c @@ -0,0 +1,1227 @@ +/****************************************************************************** + * + * Module Name: evgpeblk - GPE block creation and initialization. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evgpeblk") + +/* Local prototypes */ +static acpi_status +acpi_ev_save_method_info(acpi_handle obj_handle, + u32 level, void *obj_desc, void **return_value); + +static acpi_status +acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, + u32 level, void *info, void **return_value); + +static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 + interrupt_number); + +static acpi_status +acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt); + +static acpi_status +acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, + u32 interrupt_number); + +static acpi_status +acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block); + +/******************************************************************************* + * + * FUNCTION: acpi_ev_valid_gpe_event + * + * PARAMETERS: gpe_event_info - Info for this GPE + * + * RETURN: TRUE if the gpe_event is valid + * + * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL. + * Should be called only when the GPE lists are semaphore locked + * and not subject to change. + * + ******************************************************************************/ + +u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info) +{ + struct acpi_gpe_xrupt_info *gpe_xrupt_block; + struct acpi_gpe_block_info *gpe_block; + + ACPI_FUNCTION_ENTRY(); + + /* No need for spin lock since we are not changing any list elements */ + + /* Walk the GPE interrupt levels */ + + gpe_xrupt_block = acpi_gbl_gpe_xrupt_list_head; + while (gpe_xrupt_block) { + gpe_block = gpe_xrupt_block->gpe_block_list_head; + + /* Walk the GPE blocks on this interrupt level */ + + while (gpe_block) { + if ((&gpe_block->event_info[0] <= gpe_event_info) && + (&gpe_block-> + event_info[((acpi_size) gpe_block-> + register_count) * 8] > + gpe_event_info)) { + return (TRUE); + } + + gpe_block = gpe_block->next; + } + + gpe_xrupt_block = gpe_xrupt_block->next; + } + + return (FALSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_walk_gpe_list + * + * PARAMETERS: gpe_walk_callback - Routine called for each GPE block + * Context - Value passed to callback + * + * RETURN: Status + * + * DESCRIPTION: Walk the GPE lists. + * + ******************************************************************************/ + +acpi_status +acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context) +{ + struct acpi_gpe_block_info *gpe_block; + struct acpi_gpe_xrupt_info *gpe_xrupt_info; + acpi_status status = AE_OK; + acpi_cpu_flags flags; + + ACPI_FUNCTION_TRACE(ev_walk_gpe_list); + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Walk the interrupt level descriptor list */ + + gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; + while (gpe_xrupt_info) { + + /* Walk all Gpe Blocks attached to this interrupt level */ + + gpe_block = gpe_xrupt_info->gpe_block_list_head; + while (gpe_block) { + + /* One callback per GPE block */ + + status = + gpe_walk_callback(gpe_xrupt_info, gpe_block, + context); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_END) { /* Callback abort */ + status = AE_OK; + } + goto unlock_and_exit; + } + + gpe_block = gpe_block->next; + } + + gpe_xrupt_info = gpe_xrupt_info->next; + } + + unlock_and_exit: + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_delete_gpe_handlers + * + * PARAMETERS: gpe_xrupt_info - GPE Interrupt info + * gpe_block - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Delete all Handler objects found in the GPE data structs. + * Used only prior to termination. + * + ******************************************************************************/ + +acpi_status +acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, + void *context) +{ + struct acpi_gpe_event_info *gpe_event_info; + u32 i; + u32 j; + + ACPI_FUNCTION_TRACE(ev_delete_gpe_handlers); + + /* Examine each GPE Register within the block */ + + for (i = 0; i < gpe_block->register_count; i++) { + + /* Now look at the individual GPEs in this byte register */ + + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { + gpe_event_info = + &gpe_block-> + event_info[((acpi_size) i * + ACPI_GPE_REGISTER_WIDTH) + j]; + + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_HANDLER) { + ACPI_FREE(gpe_event_info->dispatch.handler); + gpe_event_info->dispatch.handler = NULL; + gpe_event_info->flags &= + ~ACPI_GPE_DISPATCH_MASK; + } + } + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_save_method_info + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a + * control method under the _GPE portion of the namespace. + * Extract the name and GPE type from the object, saving this + * information for quick lookup during GPE dispatch + * + * The name of each GPE control method is of the form: + * "_Lxx" or "_Exx" + * Where: + * L - means that the GPE is level triggered + * E - means that the GPE is edge triggered + * xx - is the GPE number [in HEX] + * + ******************************************************************************/ + +static acpi_status +acpi_ev_save_method_info(acpi_handle obj_handle, + u32 level, void *obj_desc, void **return_value) +{ + struct acpi_gpe_block_info *gpe_block = (void *)obj_desc; + struct acpi_gpe_event_info *gpe_event_info; + u32 gpe_number; + char name[ACPI_NAME_SIZE + 1]; + u8 type; + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_save_method_info); + + /* + * _Lxx and _Exx GPE method support + * + * 1) Extract the name from the object and convert to a string + */ + ACPI_MOVE_32_TO_32(name, + &((struct acpi_namespace_node *)obj_handle)->name. + integer); + name[ACPI_NAME_SIZE] = 0; + + /* + * 2) Edge/Level determination is based on the 2nd character + * of the method name + * + * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE + * if a _PRW object is found that points to this GPE. + */ + switch (name[1]) { + case 'L': + type = ACPI_GPE_LEVEL_TRIGGERED; + break; + + case 'E': + type = ACPI_GPE_EDGE_TRIGGERED; + break; + + default: + /* Unknown method type, just ignore it! */ + + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, + "Ignoring unknown GPE method type: %s (name not of form _Lxx or _Exx)", + name)); + return_ACPI_STATUS(AE_OK); + } + + /* Convert the last two characters of the name to the GPE Number */ + + gpe_number = ACPI_STRTOUL(&name[2], NULL, 16); + if (gpe_number == ACPI_UINT32_MAX) { + + /* Conversion failed; invalid method, just ignore it */ + + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, + "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)", + name)); + return_ACPI_STATUS(AE_OK); + } + + /* Ensure that we have a valid GPE number for this GPE block */ + + if ((gpe_number < gpe_block->block_base_number) || + (gpe_number >= + (gpe_block->block_base_number + + (gpe_block->register_count * 8)))) { + /* + * Not valid for this GPE block, just ignore it. However, it may be + * valid for a different GPE block, since GPE0 and GPE1 methods both + * appear under \_GPE. + */ + return_ACPI_STATUS(AE_OK); + } + + /* + * Now we can add this information to the gpe_event_info block for use + * during dispatch of this GPE. Default type is RUNTIME, although this may + * change when the _PRW methods are executed later. + */ + gpe_event_info = + &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; + + gpe_event_info->flags = (u8) + (type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME); + + gpe_event_info->dispatch.method_node = + (struct acpi_namespace_node *)obj_handle; + + /* Update enable mask, but don't enable the HW GPE as of yet */ + + status = acpi_ev_enable_gpe(gpe_event_info, FALSE); + + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, + "Registered GPE method %s as GPE number 0x%.2X\n", + name, gpe_number)); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_match_prw_and_gpe + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is + * not aborted on a single _PRW failure. + * + * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a + * Device. Run the _PRW method. If present, extract the GPE + * number and mark the GPE as a WAKE GPE. + * + ******************************************************************************/ + +static acpi_status +acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, + u32 level, void *info, void **return_value) +{ + struct acpi_gpe_walk_info *gpe_info = (void *)info; + struct acpi_namespace_node *gpe_device; + struct acpi_gpe_block_info *gpe_block; + struct acpi_namespace_node *target_gpe_device; + struct acpi_gpe_event_info *gpe_event_info; + union acpi_operand_object *pkg_desc; + union acpi_operand_object *obj_desc; + u32 gpe_number; + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_match_prw_and_gpe); + + /* Check for a _PRW method under this device */ + + status = acpi_ut_evaluate_object(obj_handle, METHOD_NAME__PRW, + ACPI_BTYPE_PACKAGE, &pkg_desc); + if (ACPI_FAILURE(status)) { + + /* Ignore all errors from _PRW, we don't want to abort the subsystem */ + + return_ACPI_STATUS(AE_OK); + } + + /* The returned _PRW package must have at least two elements */ + + if (pkg_desc->package.count < 2) { + goto cleanup; + } + + /* Extract pointers from the input context */ + + gpe_device = gpe_info->gpe_device; + gpe_block = gpe_info->gpe_block; + + /* + * The _PRW object must return a package, we are only interested in the + * first element + */ + obj_desc = pkg_desc->package.elements[0]; + + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + + /* Use FADT-defined GPE device (from definition of _PRW) */ + + target_gpe_device = acpi_gbl_fadt_gpe_device; + + /* Integer is the GPE number in the FADT described GPE blocks */ + + gpe_number = (u32) obj_desc->integer.value; + } else if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + + /* Package contains a GPE reference and GPE number within a GPE block */ + + if ((obj_desc->package.count < 2) || + (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[0]) != + ACPI_TYPE_LOCAL_REFERENCE) + || (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[1]) != + ACPI_TYPE_INTEGER)) { + goto cleanup; + } + + /* Get GPE block reference and decode */ + + target_gpe_device = + obj_desc->package.elements[0]->reference.node; + gpe_number = (u32) obj_desc->package.elements[1]->integer.value; + } else { + /* Unknown type, just ignore it */ + + goto cleanup; + } + + /* + * Is this GPE within this block? + * + * TRUE if and only if these conditions are true: + * 1) The GPE devices match. + * 2) The GPE index(number) is within the range of the Gpe Block + * associated with the GPE device. + */ + if ((gpe_device == target_gpe_device) && + (gpe_number >= gpe_block->block_base_number) && + (gpe_number < + gpe_block->block_base_number + (gpe_block->register_count * 8))) { + gpe_event_info = + &gpe_block->event_info[gpe_number - + gpe_block->block_base_number]; + + /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ + + gpe_event_info->flags &= + ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED); + + status = + acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + status = + acpi_ev_update_gpe_enable_masks(gpe_event_info, + ACPI_GPE_DISABLE); + } + + cleanup: + acpi_ut_remove_reference(pkg_desc); + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_get_gpe_xrupt_block + * + * PARAMETERS: interrupt_number - Interrupt for a GPE block + * + * RETURN: A GPE interrupt block + * + * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt + * block per unique interrupt level used for GPEs. Should be + * called only when the GPE lists are semaphore locked and not + * subject to change. + * + ******************************************************************************/ + +static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 + interrupt_number) +{ + struct acpi_gpe_xrupt_info *next_gpe_xrupt; + struct acpi_gpe_xrupt_info *gpe_xrupt; + acpi_status status; + acpi_cpu_flags flags; + + ACPI_FUNCTION_TRACE(ev_get_gpe_xrupt_block); + + /* No need for lock since we are not changing any list elements here */ + + next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head; + while (next_gpe_xrupt) { + if (next_gpe_xrupt->interrupt_number == interrupt_number) { + return_PTR(next_gpe_xrupt); + } + + next_gpe_xrupt = next_gpe_xrupt->next; + } + + /* Not found, must allocate a new xrupt descriptor */ + + gpe_xrupt = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_xrupt_info)); + if (!gpe_xrupt) { + return_PTR(NULL); + } + + gpe_xrupt->interrupt_number = interrupt_number; + + /* Install new interrupt descriptor with spin lock */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + if (acpi_gbl_gpe_xrupt_list_head) { + next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head; + while (next_gpe_xrupt->next) { + next_gpe_xrupt = next_gpe_xrupt->next; + } + + next_gpe_xrupt->next = gpe_xrupt; + gpe_xrupt->previous = next_gpe_xrupt; + } else { + acpi_gbl_gpe_xrupt_list_head = gpe_xrupt; + } + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + + /* Install new interrupt handler if not SCI_INT */ + + if (interrupt_number != acpi_gbl_FADT.sci_interrupt) { + status = acpi_os_install_interrupt_handler(interrupt_number, + acpi_ev_gpe_xrupt_handler, + gpe_xrupt); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not install GPE interrupt handler at level 0x%X", + interrupt_number)); + return_PTR(NULL); + } + } + + return_PTR(gpe_xrupt); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_delete_gpe_xrupt + * + * PARAMETERS: gpe_xrupt - A GPE interrupt info block + * + * RETURN: Status + * + * DESCRIPTION: Remove and free a gpe_xrupt block. Remove an associated + * interrupt handler if not the SCI interrupt. + * + ******************************************************************************/ + +static acpi_status +acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt) +{ + acpi_status status; + acpi_cpu_flags flags; + + ACPI_FUNCTION_TRACE(ev_delete_gpe_xrupt); + + /* We never want to remove the SCI interrupt handler */ + + if (gpe_xrupt->interrupt_number == acpi_gbl_FADT.sci_interrupt) { + gpe_xrupt->gpe_block_list_head = NULL; + return_ACPI_STATUS(AE_OK); + } + + /* Disable this interrupt */ + + status = + acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number, + acpi_ev_gpe_xrupt_handler); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Unlink the interrupt block with lock */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + if (gpe_xrupt->previous) { + gpe_xrupt->previous->next = gpe_xrupt->next; + } else { + /* No previous, update list head */ + + acpi_gbl_gpe_xrupt_list_head = gpe_xrupt->next; + } + + if (gpe_xrupt->next) { + gpe_xrupt->next->previous = gpe_xrupt->previous; + } + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + + /* Free the block */ + + ACPI_FREE(gpe_xrupt); + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_gpe_block + * + * PARAMETERS: gpe_block - New GPE block + * interrupt_number - Xrupt to be associated with this + * GPE block + * + * RETURN: Status + * + * DESCRIPTION: Install new GPE block with mutex support + * + ******************************************************************************/ + +static acpi_status +acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, + u32 interrupt_number) +{ + struct acpi_gpe_block_info *next_gpe_block; + struct acpi_gpe_xrupt_info *gpe_xrupt_block; + acpi_status status; + acpi_cpu_flags flags; + + ACPI_FUNCTION_TRACE(ev_install_gpe_block); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block(interrupt_number); + if (!gpe_xrupt_block) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Install the new block at the end of the list with lock */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + if (gpe_xrupt_block->gpe_block_list_head) { + next_gpe_block = gpe_xrupt_block->gpe_block_list_head; + while (next_gpe_block->next) { + next_gpe_block = next_gpe_block->next; + } + + next_gpe_block->next = gpe_block; + gpe_block->previous = next_gpe_block; + } else { + gpe_xrupt_block->gpe_block_list_head = gpe_block; + } + + gpe_block->xrupt_block = gpe_xrupt_block; + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + + unlock_and_exit: + status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_delete_gpe_block + * + * PARAMETERS: gpe_block - Existing GPE block + * + * RETURN: Status + * + * DESCRIPTION: Remove a GPE block + * + ******************************************************************************/ + +acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) +{ + acpi_status status; + acpi_cpu_flags flags; + + ACPI_FUNCTION_TRACE(ev_install_gpe_block); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Disable all GPEs in this block */ + + status = + acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block, NULL); + + if (!gpe_block->previous && !gpe_block->next) { + + /* This is the last gpe_block on this interrupt */ + + status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + } else { + /* Remove the block on this interrupt with lock */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + if (gpe_block->previous) { + gpe_block->previous->next = gpe_block->next; + } else { + gpe_block->xrupt_block->gpe_block_list_head = + gpe_block->next; + } + + if (gpe_block->next) { + gpe_block->next->previous = gpe_block->previous; + } + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + } + + acpi_current_gpe_count -= + gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH; + + /* Free the gpe_block */ + + ACPI_FREE(gpe_block->register_info); + ACPI_FREE(gpe_block->event_info); + ACPI_FREE(gpe_block); + + unlock_and_exit: + status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_create_gpe_info_blocks + * + * PARAMETERS: gpe_block - New GPE block + * + * RETURN: Status + * + * DESCRIPTION: Create the register_info and event_info blocks for this GPE block + * + ******************************************************************************/ + +static acpi_status +acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) +{ + struct acpi_gpe_register_info *gpe_register_info = NULL; + struct acpi_gpe_event_info *gpe_event_info = NULL; + struct acpi_gpe_event_info *this_event; + struct acpi_gpe_register_info *this_register; + u32 i; + u32 j; + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks); + + /* Allocate the GPE register information block */ + + gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block-> + register_count * + sizeof(struct + acpi_gpe_register_info)); + if (!gpe_register_info) { + ACPI_ERROR((AE_INFO, + "Could not allocate the GpeRegisterInfo table")); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Allocate the GPE event_info block. There are eight distinct GPEs + * per register. Initialization to zeros is sufficient. + */ + gpe_event_info = ACPI_ALLOCATE_ZEROED(((acpi_size) gpe_block-> + register_count * + ACPI_GPE_REGISTER_WIDTH) * + sizeof(struct + acpi_gpe_event_info)); + if (!gpe_event_info) { + ACPI_ERROR((AE_INFO, + "Could not allocate the GpeEventInfo table")); + status = AE_NO_MEMORY; + goto error_exit; + } + + /* Save the new Info arrays in the GPE block */ + + gpe_block->register_info = gpe_register_info; + gpe_block->event_info = gpe_event_info; + + /* + * Initialize the GPE Register and Event structures. A goal of these + * tables is to hide the fact that there are two separate GPE register + * sets in a given GPE hardware block, the status registers occupy the + * first half, and the enable registers occupy the second half. + */ + this_register = gpe_register_info; + this_event = gpe_event_info; + + for (i = 0; i < gpe_block->register_count; i++) { + + /* Init the register_info for this GPE register (8 GPEs) */ + + this_register->base_gpe_number = + (u8) (gpe_block->block_base_number + + (i * ACPI_GPE_REGISTER_WIDTH)); + + this_register->status_address.address = + gpe_block->block_address.address + i; + + this_register->enable_address.address = + gpe_block->block_address.address + i + + gpe_block->register_count; + + this_register->status_address.space_id = + gpe_block->block_address.space_id; + this_register->enable_address.space_id = + gpe_block->block_address.space_id; + this_register->status_address.bit_width = + ACPI_GPE_REGISTER_WIDTH; + this_register->enable_address.bit_width = + ACPI_GPE_REGISTER_WIDTH; + this_register->status_address.bit_offset = 0; + this_register->enable_address.bit_offset = 0; + + /* Init the event_info for each GPE within this register */ + + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { + this_event->gpe_number = + (u8) (this_register->base_gpe_number + j); + this_event->register_info = this_register; + this_event++; + } + + /* Disable all GPEs within this register */ + + status = acpi_write(0x00, &this_register->enable_address); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + + /* Clear any pending GPE events within this register */ + + status = acpi_write(0xFF, &this_register->status_address); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + + this_register++; + } + + return_ACPI_STATUS(AE_OK); + + error_exit: + if (gpe_register_info) { + ACPI_FREE(gpe_register_info); + } + if (gpe_event_info) { + ACPI_FREE(gpe_event_info); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_create_gpe_block + * + * PARAMETERS: gpe_device - Handle to the parent GPE block + * gpe_block_address - Address and space_iD + * register_count - Number of GPE register pairs in the block + * gpe_block_base_number - Starting GPE number for the block + * interrupt_number - H/W interrupt for the block + * return_gpe_block - Where the new block descriptor is returned + * + * RETURN: Status + * + * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within + * the block are disabled at exit. + * Note: Assumes namespace is locked. + * + ******************************************************************************/ + +acpi_status +acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, + struct acpi_generic_address *gpe_block_address, + u32 register_count, + u8 gpe_block_base_number, + u32 interrupt_number, + struct acpi_gpe_block_info **return_gpe_block) +{ + acpi_status status; + struct acpi_gpe_block_info *gpe_block; + + ACPI_FUNCTION_TRACE(ev_create_gpe_block); + + if (!register_count) { + return_ACPI_STATUS(AE_OK); + } + + /* Allocate a new GPE block */ + + gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info)); + if (!gpe_block) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Initialize the new GPE block */ + + gpe_block->node = gpe_device; + gpe_block->register_count = register_count; + gpe_block->block_base_number = gpe_block_base_number; + + ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address, + sizeof(struct acpi_generic_address)); + + /* + * Create the register_info and event_info sub-structures + * Note: disables and clears all GPEs in the block + */ + status = acpi_ev_create_gpe_info_blocks(gpe_block); + if (ACPI_FAILURE(status)) { + ACPI_FREE(gpe_block); + return_ACPI_STATUS(status); + } + + /* Install the new block in the global lists */ + + status = acpi_ev_install_gpe_block(gpe_block, interrupt_number); + if (ACPI_FAILURE(status)) { + ACPI_FREE(gpe_block); + return_ACPI_STATUS(status); + } + + /* Find all GPE methods (_Lxx, _Exx) for this block */ + + status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, + ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, + acpi_ev_save_method_info, gpe_block, + NULL); + + /* Return the new block */ + + if (return_gpe_block) { + (*return_gpe_block) = gpe_block; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INIT, + "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", + (u32) gpe_block->block_base_number, + (u32) (gpe_block->block_base_number + + ((gpe_block->register_count * + ACPI_GPE_REGISTER_WIDTH) - 1)), + gpe_device->name.ascii, gpe_block->register_count, + interrupt_number)); + + /* Update global count of currently available GPEs */ + + acpi_current_gpe_count += register_count * ACPI_GPE_REGISTER_WIDTH; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_initialize_gpe_block + * + * PARAMETERS: gpe_device - Handle to the parent GPE block + * gpe_block - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Initialize and enable a GPE block. First find and run any + * _PRT methods associated with the block, then enable the + * appropriate GPEs. + * Note: Assumes namespace is locked. + * + ******************************************************************************/ + +acpi_status +acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, + struct acpi_gpe_block_info *gpe_block) +{ + acpi_status status; + struct acpi_gpe_event_info *gpe_event_info; + struct acpi_gpe_walk_info gpe_info; + u32 wake_gpe_count; + u32 gpe_enabled_count; + u32 i; + u32 j; + + ACPI_FUNCTION_TRACE(ev_initialize_gpe_block); + + /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */ + + if (!gpe_block) { + return_ACPI_STATUS(AE_OK); + } + + /* + * Runtime option: Should wake GPEs be enabled at runtime? The default + * is no, they should only be enabled just as the machine goes to sleep. + */ + if (acpi_gbl_leave_wake_gpes_disabled) { + /* + * Differentiate runtime vs wake GPEs, via the _PRW control methods. + * Each GPE that has one or more _PRWs that reference it is by + * definition a wake GPE and will not be enabled while the machine + * is running. + */ + gpe_info.gpe_block = gpe_block; + gpe_info.gpe_device = gpe_device; + + status = + acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, + acpi_ev_match_prw_and_gpe, &gpe_info, + NULL); + } + + /* + * Enable all GPEs in this block that have these attributes: + * 1) are "runtime" or "run/wake" GPEs, and + * 2) have a corresponding _Lxx or _Exx method + * + * Any other GPEs within this block must be enabled via the acpi_enable_gpe() + * external interface. + */ + wake_gpe_count = 0; + gpe_enabled_count = 0; + + for (i = 0; i < gpe_block->register_count; i++) { + for (j = 0; j < 8; j++) { + + /* Get the info block for this particular GPE */ + + gpe_event_info = + &gpe_block-> + event_info[((acpi_size) i * + ACPI_GPE_REGISTER_WIDTH) + j]; + + if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_METHOD) + && (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) { + gpe_enabled_count++; + } + + if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) { + wake_gpe_count++; + } + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_INIT, + "Found %u Wake, Enabled %u Runtime GPEs in this block\n", + wake_gpe_count, gpe_enabled_count)); + + /* Enable all valid runtime GPEs found above */ + + status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block, NULL); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not enable GPEs in GpeBlock %p", + gpe_block)); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_gpe_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize the GPE data structures + * + ******************************************************************************/ + +acpi_status acpi_ev_gpe_initialize(void) +{ + u32 register_count0 = 0; + u32 register_count1 = 0; + u32 gpe_number_max = 0; + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_gpe_initialize); + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Initialize the GPE Block(s) defined in the FADT + * + * Why the GPE register block lengths are divided by 2: From the ACPI Spec, + * section "General-Purpose Event Registers", we have: + * + * "Each register block contains two registers of equal length + * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the + * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN + * The length of the GPE1_STS and GPE1_EN registers is equal to + * half the GPE1_LEN. If a generic register block is not supported + * then its respective block pointer and block length values in the + * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need + * to be the same size." + */ + + /* + * Determine the maximum GPE number for this machine. + * + * Note: both GPE0 and GPE1 are optional, and either can exist without + * the other. + * + * If EITHER the register length OR the block address are zero, then that + * particular block is not supported. + */ + if (acpi_gbl_FADT.gpe0_block_length && + acpi_gbl_FADT.xgpe0_block.address) { + + /* GPE block 0 exists (has both length and address > 0) */ + + register_count0 = (u16) (acpi_gbl_FADT.gpe0_block_length / 2); + + gpe_number_max = + (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1; + + /* Install GPE Block 0 */ + + status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, + &acpi_gbl_FADT.xgpe0_block, + register_count0, 0, + acpi_gbl_FADT.sci_interrupt, + &acpi_gbl_gpe_fadt_blocks[0]); + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not create GPE Block 0")); + } + } + + if (acpi_gbl_FADT.gpe1_block_length && + acpi_gbl_FADT.xgpe1_block.address) { + + /* GPE block 1 exists (has both length and address > 0) */ + + register_count1 = (u16) (acpi_gbl_FADT.gpe1_block_length / 2); + + /* Check for GPE0/GPE1 overlap (if both banks exist) */ + + if ((register_count0) && + (gpe_number_max >= acpi_gbl_FADT.gpe1_base)) { + ACPI_ERROR((AE_INFO, + "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1", + gpe_number_max, acpi_gbl_FADT.gpe1_base, + acpi_gbl_FADT.gpe1_base + + ((register_count1 * + ACPI_GPE_REGISTER_WIDTH) - 1))); + + /* Ignore GPE1 block by setting the register count to zero */ + + register_count1 = 0; + } else { + /* Install GPE Block 1 */ + + status = + acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, + &acpi_gbl_FADT.xgpe1_block, + register_count1, + acpi_gbl_FADT.gpe1_base, + acpi_gbl_FADT. + sci_interrupt, + &acpi_gbl_gpe_fadt_blocks + [1]); + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not create GPE Block 1")); + } + + /* + * GPE0 and GPE1 do not have to be contiguous in the GPE number + * space. However, GPE0 always starts at GPE number zero. + */ + gpe_number_max = acpi_gbl_FADT.gpe1_base + + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1); + } + } + + /* Exit if there are no GPE registers */ + + if ((register_count0 + register_count1) == 0) { + + /* GPEs are not required by ACPI, this is OK */ + + ACPI_DEBUG_PRINT((ACPI_DB_INIT, + "There are no GPE blocks defined in the FADT\n")); + status = AE_OK; + goto cleanup; + } + + /* Check for Max GPE number out-of-range */ + + if (gpe_number_max > ACPI_GPE_MAX) { + ACPI_ERROR((AE_INFO, + "Maximum GPE number from FADT is too large: 0x%X", + gpe_number_max)); + status = AE_BAD_VALUE; + goto cleanup; + } + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c new file mode 100644 index 000000000000..16f2c1a00167 --- /dev/null +++ b/drivers/acpi/acpica/evmisc.c @@ -0,0 +1,621 @@ +/****************************************************************************** + * + * Module Name: evmisc - Miscellaneous event manager support functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evmisc") + +/* Local prototypes */ +static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); + +static u32 acpi_ev_global_lock_handler(void *context); + +static acpi_status acpi_ev_remove_global_lock_handler(void); + +/******************************************************************************* + * + * FUNCTION: acpi_ev_is_notify_object + * + * PARAMETERS: Node - Node to check + * + * RETURN: TRUE if notifies allowed on this object + * + * DESCRIPTION: Check type of node for a object that supports notifies. + * + * TBD: This could be replaced by a flag bit in the node. + * + ******************************************************************************/ + +u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node) +{ + switch (node->type) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + /* + * These are the ONLY objects that can receive ACPI notifications + */ + return (TRUE); + + default: + return (FALSE); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_queue_notify_request + * + * PARAMETERS: Node - NS node for the notified object + * notify_value - Value from the Notify() request + * + * RETURN: Status + * + * DESCRIPTION: Dispatch a device notification event to a previously + * installed handler. + * + ******************************************************************************/ + +acpi_status +acpi_ev_queue_notify_request(struct acpi_namespace_node * node, + u32 notify_value) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj = NULL; + union acpi_generic_state *notify_info; + acpi_status status = AE_OK; + + ACPI_FUNCTION_NAME(ev_queue_notify_request); + + /* + * For value 3 (Ejection Request), some device method may need to be run. + * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need + * to be run. + * For value 0x80 (Status Change) on the power button or sleep button, + * initiate soft-off or sleep operation? + */ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", + acpi_ut_get_node_name(node), node, notify_value, + acpi_ut_get_notify_name(notify_value))); + + /* Get the notify object attached to the NS Node */ + + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + + /* We have the notify object, Get the right handler */ + + switch (node->type) { + + /* Notify allowed only on these types */ + + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_PROCESSOR: + + if (notify_value <= ACPI_MAX_SYS_NOTIFY) { + handler_obj = + obj_desc->common_notify.system_notify; + } else { + handler_obj = + obj_desc->common_notify.device_notify; + } + break; + + default: + + /* All other types are not supported */ + + return (AE_TYPE); + } + } + + /* + * If there is any handler to run, schedule the dispatcher. + * Check for: + * 1) Global system notify handler + * 2) Global device notify handler + * 3) Per-device notify handler + */ + if ((acpi_gbl_system_notify.handler + && (notify_value <= ACPI_MAX_SYS_NOTIFY)) + || (acpi_gbl_device_notify.handler + && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { + notify_info = acpi_ut_create_generic_state(); + if (!notify_info) { + return (AE_NO_MEMORY); + } + + if (!handler_obj) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Executing system notify handler for Notify (%4.4s, %X) node %p\n", + acpi_ut_get_node_name(node), + notify_value, node)); + } + + notify_info->common.descriptor_type = + ACPI_DESC_TYPE_STATE_NOTIFY; + notify_info->notify.node = node; + notify_info->notify.value = (u16) notify_value; + notify_info->notify.handler_obj = handler_obj; + + status = + acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, + notify_info); + if (ACPI_FAILURE(status)) { + acpi_ut_delete_generic_state(notify_info); + } + } else { + /* There is no notify handler (per-device or system) for this device */ + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "No notify handler for Notify (%4.4s, %X) node %p\n", + acpi_ut_get_node_name(node), notify_value, + node)); + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_notify_dispatch + * + * PARAMETERS: Context - To be passed to the notify handler + * + * RETURN: None. + * + * DESCRIPTION: Dispatch a device notification event to a previously + * installed handler. + * + ******************************************************************************/ + +static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) +{ + union acpi_generic_state *notify_info = + (union acpi_generic_state *)context; + acpi_notify_handler global_handler = NULL; + void *global_context = NULL; + union acpi_operand_object *handler_obj; + + ACPI_FUNCTION_ENTRY(); + + /* + * We will invoke a global notify handler if installed. This is done + * _before_ we invoke the per-device handler attached to the device. + */ + if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) { + + /* Global system notification handler */ + + if (acpi_gbl_system_notify.handler) { + global_handler = acpi_gbl_system_notify.handler; + global_context = acpi_gbl_system_notify.context; + } + } else { + /* Global driver notification handler */ + + if (acpi_gbl_device_notify.handler) { + global_handler = acpi_gbl_device_notify.handler; + global_context = acpi_gbl_device_notify.context; + } + } + + /* Invoke the system handler first, if present */ + + if (global_handler) { + global_handler(notify_info->notify.node, + notify_info->notify.value, global_context); + } + + /* Now invoke the per-device handler, if present */ + + handler_obj = notify_info->notify.handler_obj; + if (handler_obj) { + handler_obj->notify.handler(notify_info->notify.node, + notify_info->notify.value, + handler_obj->notify.context); + } + + /* All done with the info object */ + + acpi_ut_delete_generic_state(notify_info); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_global_lock_handler + * + * PARAMETERS: Context - From thread interface, not used + * + * RETURN: ACPI_INTERRUPT_HANDLED + * + * DESCRIPTION: Invoked directly from the SCI handler when a global lock + * release interrupt occurs. Attempt to acquire the global lock, + * if successful, signal the thread waiting for the lock. + * + * NOTE: Assumes that the semaphore can be signaled from interrupt level. If + * this is not possible for some reason, a separate thread will have to be + * scheduled to do this. + * + ******************************************************************************/ + +static u32 acpi_ev_global_lock_handler(void *context) +{ + u8 acquired = FALSE; + + /* + * Attempt to get the lock. + * + * If we don't get it now, it will be marked pending and we will + * take another interrupt when it becomes free. + */ + ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); + if (acquired) { + + /* Got the lock, now wake all threads waiting for it */ + + acpi_gbl_global_lock_acquired = TRUE; + /* Send a unit to the semaphore */ + + if (ACPI_FAILURE + (acpi_os_signal_semaphore + (acpi_gbl_global_lock_semaphore, 1))) { + ACPI_ERROR((AE_INFO, + "Could not signal Global Lock semaphore")); + } + } + + return (ACPI_INTERRUPT_HANDLED); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_init_global_lock_handler + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for the global lock release event + * + ******************************************************************************/ + +acpi_status acpi_ev_init_global_lock_handler(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); + + /* Attempt installation of the global lock handler */ + + status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL, + acpi_ev_global_lock_handler, + NULL); + + /* + * If the global lock does not exist on this platform, the attempt to + * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick). + * Map to AE_OK, but mark global lock as not present. Any attempt to + * actually use the global lock will be flagged with an error. + */ + if (status == AE_NO_HARDWARE_RESPONSE) { + ACPI_ERROR((AE_INFO, + "No response from Global Lock hardware, disabling lock")); + + acpi_gbl_global_lock_present = FALSE; + return_ACPI_STATUS(AE_OK); + } + + acpi_gbl_global_lock_present = TRUE; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_remove_global_lock_handler + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Remove the handler for the Global Lock + * + ******************************************************************************/ + +static acpi_status acpi_ev_remove_global_lock_handler(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_remove_global_lock_handler); + + acpi_gbl_global_lock_present = FALSE; + status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL, + acpi_ev_global_lock_handler); + + return_ACPI_STATUS(status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_ev_acquire_global_lock + * + * PARAMETERS: Timeout - Max time to wait for the lock, in millisec. + * + * RETURN: Status + * + * DESCRIPTION: Attempt to gain ownership of the Global Lock. + * + * MUTEX: Interpreter must be locked + * + * Note: The original implementation allowed multiple threads to "acquire" the + * Global Lock, and the OS would hold the lock until the last thread had + * released it. However, this could potentially starve the BIOS out of the + * lock, especially in the case where there is a tight handshake between the + * Embedded Controller driver and the BIOS. Therefore, this implementation + * allows only one thread to acquire the HW Global Lock at a time, and makes + * the global lock appear as a standard mutex on the OS side. + * + *****************************************************************************/ +static acpi_thread_id acpi_ev_global_lock_thread_id; +static int acpi_ev_global_lock_acquired; + +acpi_status acpi_ev_acquire_global_lock(u16 timeout) +{ + acpi_status status = AE_OK; + u8 acquired = FALSE; + + ACPI_FUNCTION_TRACE(ev_acquire_global_lock); + + /* + * Only one thread can acquire the GL at a time, the global_lock_mutex + * enforces this. This interface releases the interpreter if we must wait. + */ + status = acpi_ex_system_wait_mutex( + acpi_gbl_global_lock_mutex->mutex.os_mutex, 0); + if (status == AE_TIME) { + if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { + acpi_ev_global_lock_acquired++; + return AE_OK; + } + } + + if (ACPI_FAILURE(status)) { + status = acpi_ex_system_wait_mutex( + acpi_gbl_global_lock_mutex->mutex.os_mutex, + timeout); + } + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ev_global_lock_thread_id = acpi_os_get_thread_id(); + acpi_ev_global_lock_acquired++; + + /* + * Update the global lock handle and check for wraparound. The handle is + * only used for the external global lock interfaces, but it is updated + * here to properly handle the case where a single thread may acquire the + * lock via both the AML and the acpi_acquire_global_lock interfaces. The + * handle is therefore updated on the first acquire from a given thread + * regardless of where the acquisition request originated. + */ + acpi_gbl_global_lock_handle++; + if (acpi_gbl_global_lock_handle == 0) { + acpi_gbl_global_lock_handle = 1; + } + + /* + * Make sure that a global lock actually exists. If not, just treat the + * lock as a standard mutex. + */ + if (!acpi_gbl_global_lock_present) { + acpi_gbl_global_lock_acquired = TRUE; + return_ACPI_STATUS(AE_OK); + } + + /* Attempt to acquire the actual hardware lock */ + + ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); + if (acquired) { + + /* We got the lock */ + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Acquired hardware Global Lock\n")); + + acpi_gbl_global_lock_acquired = TRUE; + return_ACPI_STATUS(AE_OK); + } + + /* + * Did not get the lock. The pending bit was set above, and we must now + * wait until we get the global lock released interrupt. + */ + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n")); + + /* + * Wait for handshake with the global lock interrupt handler. + * This interface releases the interpreter if we must wait. + */ + status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, + ACPI_WAIT_FOREVER); + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_release_global_lock + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Releases ownership of the Global Lock. + * + ******************************************************************************/ + +acpi_status acpi_ev_release_global_lock(void) +{ + u8 pending = FALSE; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ev_release_global_lock); + + /* Lock must be already acquired */ + + if (!acpi_gbl_global_lock_acquired) { + ACPI_WARNING((AE_INFO, + "Cannot release the ACPI Global Lock, it has not been acquired")); + return_ACPI_STATUS(AE_NOT_ACQUIRED); + } + + acpi_ev_global_lock_acquired--; + if (acpi_ev_global_lock_acquired > 0) { + return AE_OK; + } + + if (acpi_gbl_global_lock_present) { + + /* Allow any thread to release the lock */ + + ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_FACS, pending); + + /* + * If the pending bit was set, we must write GBL_RLS to the control + * register + */ + if (pending) { + status = + acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE, + 1); + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Released hardware Global Lock\n")); + } + + acpi_gbl_global_lock_acquired = FALSE; + + /* Release the local GL mutex */ + acpi_ev_global_lock_thread_id = NULL; + acpi_ev_global_lock_acquired = 0; + acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex); + return_ACPI_STATUS(status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_ev_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Disable events and free memory allocated for table storage. + * + ******************************************************************************/ + +void acpi_ev_terminate(void) +{ + u32 i; + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_terminate); + + if (acpi_gbl_events_initialized) { + /* + * Disable all event-related functionality. In all cases, on error, + * print a message but obviously we don't abort. + */ + + /* Disable all fixed events */ + + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + status = acpi_disable_event(i, 0); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not disable fixed event %d", + (u32) i)); + } + } + + /* Disable all GPEs in all GPE blocks */ + + status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); + + /* Remove SCI handler */ + + status = acpi_ev_remove_sci_handler(); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); + } + + status = acpi_ev_remove_global_lock_handler(); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not remove Global Lock handler")); + } + } + + /* Deallocate all handler objects installed within GPE info structs */ + + status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL); + + /* Return to original mode if necessary */ + + if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) { + status = acpi_disable(); + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, "AcpiDisable failed")); + } + } + return_VOID; +} diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c new file mode 100644 index 000000000000..7346093f43ed --- /dev/null +++ b/drivers/acpi/acpica/evregion.c @@ -0,0 +1,1070 @@ +/****************************************************************************** + * + * Module Name: evregion - ACPI address_space (op_region) handler dispatch + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evregion") + +/* Local prototypes */ +static acpi_status +acpi_ev_reg_run(acpi_handle obj_handle, + u32 level, void *context, void **return_value); + +static acpi_status +acpi_ev_install_handler(acpi_handle obj_handle, + u32 level, void *context, void **return_value); + +/* These are the address spaces that will get default handlers */ + +#define ACPI_NUM_DEFAULT_SPACES 4 + +static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { + ACPI_ADR_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_IO, + ACPI_ADR_SPACE_PCI_CONFIG, + ACPI_ADR_SPACE_DATA_TABLE +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_region_handlers + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Installs the core subsystem default address space handlers. + * + ******************************************************************************/ + +acpi_status acpi_ev_install_region_handlers(void) +{ + acpi_status status; + u32 i; + + ACPI_FUNCTION_TRACE(ev_install_region_handlers); + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * All address spaces (PCI Config, EC, SMBus) are scope dependent and + * registration must occur for a specific device. + * + * In the case of the system memory and IO address spaces there is + * currently no device associated with the address space. For these we + * use the root. + * + * We install the default PCI config space handler at the root so that + * this space is immediately available even though the we have not + * enumerated all the PCI Root Buses yet. This is to conform to the ACPI + * specification which states that the PCI config space must be always + * available -- even though we are nowhere near ready to find the PCI root + * buses at this point. + * + * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler + * has already been installed (via acpi_install_address_space_handler). + * Similar for AE_SAME_HANDLER. + */ + for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { + status = acpi_ev_install_space_handler(acpi_gbl_root_node, + acpi_gbl_default_address_spaces + [i], + ACPI_DEFAULT_HANDLER, + NULL, NULL); + switch (status) { + case AE_OK: + case AE_SAME_HANDLER: + case AE_ALREADY_EXISTS: + + /* These exceptions are all OK */ + + status = AE_OK; + break; + + default: + + goto unlock_and_exit; + } + } + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_initialize_op_regions + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Execute _REG methods for all Operation Regions that have + * an installed default region handler. + * + ******************************************************************************/ + +acpi_status acpi_ev_initialize_op_regions(void) +{ + acpi_status status; + u32 i; + + ACPI_FUNCTION_TRACE(ev_initialize_op_regions); + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Run the _REG methods for op_regions in each default address space */ + + for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { + /* + * TBD: Make sure handler is the DEFAULT handler, otherwise + * _REG will have already been run. + */ + status = acpi_ev_execute_reg_methods(acpi_gbl_root_node, + acpi_gbl_default_address_spaces + [i]); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_execute_reg_method + * + * PARAMETERS: region_obj - Region object + * Function - Passed to _REG: On (1) or Off (0) + * + * RETURN: Status + * + * DESCRIPTION: Execute _REG method for a region + * + ******************************************************************************/ + +acpi_status +acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) +{ + struct acpi_evaluate_info *info; + union acpi_operand_object *args[3]; + union acpi_operand_object *region_obj2; + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_execute_reg_method); + + region_obj2 = acpi_ns_get_secondary_object(region_obj); + if (!region_obj2) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + if (region_obj2->extra.method_REG == NULL) { + return_ACPI_STATUS(AE_OK); + } + + /* Allocate and initialize the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->prefix_node = region_obj2->extra.method_REG; + info->pathname = NULL; + info->parameters = args; + info->flags = ACPI_IGNORE_RETURN_VALUE; + + /* + * The _REG method has two arguments: + * + * Arg0 - Integer: + * Operation region space ID Same value as region_obj->Region.space_id + * + * Arg1 - Integer: + * connection status 1 for connecting the handler, 0 for disconnecting + * the handler (Passed as a parameter) + */ + args[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!args[0]) { + status = AE_NO_MEMORY; + goto cleanup1; + } + + args[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!args[1]) { + status = AE_NO_MEMORY; + goto cleanup2; + } + + /* Setup the parameter objects */ + + args[0]->integer.value = region_obj->region.space_id; + args[1]->integer.value = function; + args[2] = NULL; + + /* Execute the method, no return value */ + + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_METHOD, info->prefix_node, NULL)); + + status = acpi_ns_evaluate(info); + acpi_ut_remove_reference(args[1]); + + cleanup2: + acpi_ut_remove_reference(args[0]); + + cleanup1: + ACPI_FREE(info); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_address_space_dispatch + * + * PARAMETERS: region_obj - Internal region object + * Function - Read or Write operation + * Address - Where in the space to read or write + * bit_width - Field width in bits (8, 16, 32, or 64) + * Value - Pointer to in or out value, must be + * full 64-bit acpi_integer + * + * RETURN: Status + * + * DESCRIPTION: Dispatch an address space or operation region access to + * a previously installed handler. + * + ******************************************************************************/ + +acpi_status +acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + u32 function, + acpi_physical_address address, + u32 bit_width, acpi_integer * value) +{ + acpi_status status; + acpi_adr_space_handler handler; + acpi_adr_space_setup region_setup; + union acpi_operand_object *handler_desc; + union acpi_operand_object *region_obj2; + void *region_context = NULL; + + ACPI_FUNCTION_TRACE(ev_address_space_dispatch); + + region_obj2 = acpi_ns_get_secondary_object(region_obj); + if (!region_obj2) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Ensure that there is a handler associated with this region */ + + handler_desc = region_obj->region.handler; + if (!handler_desc) { + ACPI_ERROR((AE_INFO, + "No handler for Region [%4.4s] (%p) [%s]", + acpi_ut_get_node_name(region_obj->region.node), + region_obj, + acpi_ut_get_region_name(region_obj->region. + space_id))); + + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* + * It may be the case that the region has never been initialized. + * Some types of regions require special init code + */ + if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { + + /* This region has not been initialized yet, do it */ + + region_setup = handler_desc->address_space.setup; + if (!region_setup) { + + /* No initialization routine, exit with error */ + + ACPI_ERROR((AE_INFO, + "No init routine for region(%p) [%s]", + region_obj, + acpi_ut_get_region_name(region_obj->region. + space_id))); + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* + * We must exit the interpreter because the region setup will + * potentially execute control methods (for example, the _REG method + * for this region) + */ + acpi_ex_exit_interpreter(); + + status = region_setup(region_obj, ACPI_REGION_ACTIVATE, + handler_desc->address_space.context, + ®ion_context); + + /* Re-enter the interpreter */ + + acpi_ex_enter_interpreter(); + + /* Check for failure of the Region Setup */ + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During region initialization: [%s]", + acpi_ut_get_region_name(region_obj-> + region. + space_id))); + return_ACPI_STATUS(status); + } + + /* Region initialization may have been completed by region_setup */ + + if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { + region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; + + if (region_obj2->extra.region_context) { + + /* The handler for this region was already installed */ + + ACPI_FREE(region_context); + } else { + /* + * Save the returned context for use in all accesses to + * this particular region + */ + region_obj2->extra.region_context = + region_context; + } + } + } + + /* We have everything we need, we can invoke the address space handler */ + + handler = handler_desc->address_space.handler; + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", + ®ion_obj->region.handler->address_space, handler, + ACPI_FORMAT_NATIVE_UINT(address), + acpi_ut_get_region_name(region_obj->region. + space_id))); + + if (!(handler_desc->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + /* + * For handlers other than the default (supplied) handlers, we must + * exit the interpreter because the handler *might* block -- we don't + * know what it will do, so we can't hold the lock on the intepreter. + */ + acpi_ex_exit_interpreter(); + } + + /* Call the handler */ + + status = handler(function, address, bit_width, value, + handler_desc->address_space.context, + region_obj2->extra.region_context); + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]", + acpi_ut_get_region_name(region_obj->region. + space_id))); + } + + if (!(handler_desc->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + /* + * We just returned from a non-default handler, we must re-enter the + * interpreter + */ + acpi_ex_enter_interpreter(); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_detach_region + * + * PARAMETERS: region_obj - Region Object + * acpi_ns_is_locked - Namespace Region Already Locked? + * + * RETURN: None + * + * DESCRIPTION: Break the association between the handler and the region + * this is a two way association. + * + ******************************************************************************/ + +void +acpi_ev_detach_region(union acpi_operand_object *region_obj, + u8 acpi_ns_is_locked) +{ + union acpi_operand_object *handler_obj; + union acpi_operand_object *obj_desc; + union acpi_operand_object **last_obj_ptr; + acpi_adr_space_setup region_setup; + void **region_context; + union acpi_operand_object *region_obj2; + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_detach_region); + + region_obj2 = acpi_ns_get_secondary_object(region_obj); + if (!region_obj2) { + return_VOID; + } + region_context = ®ion_obj2->extra.region_context; + + /* Get the address handler from the region object */ + + handler_obj = region_obj->region.handler; + if (!handler_obj) { + + /* This region has no handler, all done */ + + return_VOID; + } + + /* Find this region in the handler's list */ + + obj_desc = handler_obj->address_space.region_list; + last_obj_ptr = &handler_obj->address_space.region_list; + + while (obj_desc) { + + /* Is this the correct Region? */ + + if (obj_desc == region_obj) { + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Removing Region %p from address handler %p\n", + region_obj, handler_obj)); + + /* This is it, remove it from the handler's list */ + + *last_obj_ptr = obj_desc->region.next; + obj_desc->region.next = NULL; /* Must clear field */ + + if (acpi_ns_is_locked) { + status = + acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_VOID; + } + } + + /* Now stop region accesses by executing the _REG method */ + + status = acpi_ev_execute_reg_method(region_obj, 0); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "from region _REG, [%s]", + acpi_ut_get_region_name + (region_obj->region.space_id))); + } + + if (acpi_ns_is_locked) { + status = + acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_VOID; + } + } + + /* + * If the region has been activated, call the setup handler with + * the deactivate notification + */ + if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { + region_setup = handler_obj->address_space.setup; + status = + region_setup(region_obj, + ACPI_REGION_DEACTIVATE, + handler_obj->address_space. + context, region_context); + + /* Init routine may fail, Just ignore errors */ + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "from region handler - deactivate, [%s]", + acpi_ut_get_region_name + (region_obj->region. + space_id))); + } + + region_obj->region.flags &= + ~(AOPOBJ_SETUP_COMPLETE); + } + + /* + * Remove handler reference in the region + * + * NOTE: this doesn't mean that the region goes away, the region + * is just inaccessible as indicated to the _REG method + * + * If the region is on the handler's list, this must be the + * region's handler + */ + region_obj->region.handler = NULL; + acpi_ut_remove_reference(handler_obj); + + return_VOID; + } + + /* Walk the linked list of handlers */ + + last_obj_ptr = &obj_desc->region.next; + obj_desc = obj_desc->region.next; + } + + /* If we get here, the region was not in the handler's region list */ + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Cannot remove region %p from address handler %p\n", + region_obj, handler_obj)); + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_attach_region + * + * PARAMETERS: handler_obj - Handler Object + * region_obj - Region Object + * acpi_ns_is_locked - Namespace Region Already Locked? + * + * RETURN: None + * + * DESCRIPTION: Create the association between the handler and the region + * this is a two way association. + * + ******************************************************************************/ + +acpi_status +acpi_ev_attach_region(union acpi_operand_object *handler_obj, + union acpi_operand_object *region_obj, + u8 acpi_ns_is_locked) +{ + + ACPI_FUNCTION_TRACE(ev_attach_region); + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Adding Region [%4.4s] %p to address handler %p [%s]\n", + acpi_ut_get_node_name(region_obj->region.node), + region_obj, handler_obj, + acpi_ut_get_region_name(region_obj->region. + space_id))); + + /* Link this region to the front of the handler's list */ + + region_obj->region.next = handler_obj->address_space.region_list; + handler_obj->address_space.region_list = region_obj; + + /* Install the region's handler */ + + if (region_obj->region.handler) { + return_ACPI_STATUS(AE_ALREADY_EXISTS); + } + + region_obj->region.handler = handler_obj; + acpi_ut_add_reference(handler_obj); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_handler + * + * PARAMETERS: walk_namespace callback + * + * DESCRIPTION: This routine installs an address handler into objects that are + * of type Region or Device. + * + * If the Object is a Device, and the device has a handler of + * the same type then the search is terminated in that branch. + * + * This is because the existing handler is closer in proximity + * to any more regions than the one we are trying to install. + * + ******************************************************************************/ + +static acpi_status +acpi_ev_install_handler(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + union acpi_operand_object *handler_obj; + union acpi_operand_object *next_handler_obj; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_NAME(ev_install_handler); + + handler_obj = (union acpi_operand_object *)context; + + /* Parameter validation */ + + if (!handler_obj) { + return (AE_OK); + } + + /* Convert and validate the device handle */ + + node = acpi_ns_map_handle_to_node(obj_handle); + if (!node) { + return (AE_BAD_PARAMETER); + } + + /* + * We only care about regions and objects that are allowed to have + * address space handlers + */ + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { + return (AE_OK); + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + + /* No object, just exit */ + + return (AE_OK); + } + + /* Devices are handled different than regions */ + + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) { + + /* Check if this Device already has a handler for this address space */ + + next_handler_obj = obj_desc->device.handler; + while (next_handler_obj) { + + /* Found a handler, is it for the same address space? */ + + if (next_handler_obj->address_space.space_id == + handler_obj->address_space.space_id) { + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Found handler for region [%s] in device %p(%p) handler %p\n", + acpi_ut_get_region_name + (handler_obj->address_space. + space_id), obj_desc, + next_handler_obj, + handler_obj)); + + /* + * Since the object we found it on was a device, then it + * means that someone has already installed a handler for + * the branch of the namespace from this device on. Just + * bail out telling the walk routine to not traverse this + * branch. This preserves the scoping rule for handlers. + */ + return (AE_CTRL_DEPTH); + } + + /* Walk the linked list of handlers attached to this device */ + + next_handler_obj = next_handler_obj->address_space.next; + } + + /* + * As long as the device didn't have a handler for this space we + * don't care about it. We just ignore it and proceed. + */ + return (AE_OK); + } + + /* Object is a Region */ + + if (obj_desc->region.space_id != handler_obj->address_space.space_id) { + + /* This region is for a different address space, just ignore it */ + + return (AE_OK); + } + + /* + * Now we have a region and it is for the handler's address space type. + * + * First disconnect region for any previous handler (if any) + */ + acpi_ev_detach_region(obj_desc, FALSE); + + /* Connect the region to the new handler */ + + status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_space_handler + * + * PARAMETERS: Node - Namespace node for the device + * space_id - The address space ID + * Handler - Address of the handler + * Setup - Address of the setup function + * Context - Value passed to the handler on each access + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for all op_regions of a given space_id. + * Assumes namespace is locked + * + ******************************************************************************/ + +acpi_status +acpi_ev_install_space_handler(struct acpi_namespace_node * node, + acpi_adr_space_type space_id, + acpi_adr_space_handler handler, + acpi_adr_space_setup setup, void *context) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + acpi_status status; + acpi_object_type type; + u8 flags = 0; + + ACPI_FUNCTION_TRACE(ev_install_space_handler); + + /* + * This registration is valid for only the types below and the root. This + * is where the default handlers get placed. + */ + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_PROCESSOR) && + (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + if (handler == ACPI_DEFAULT_HANDLER) { + flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; + + switch (space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + handler = acpi_ex_system_memory_space_handler; + setup = acpi_ev_system_memory_region_setup; + break; + + case ACPI_ADR_SPACE_SYSTEM_IO: + handler = acpi_ex_system_io_space_handler; + setup = acpi_ev_io_space_region_setup; + break; + + case ACPI_ADR_SPACE_PCI_CONFIG: + handler = acpi_ex_pci_config_space_handler; + setup = acpi_ev_pci_config_region_setup; + break; + + case ACPI_ADR_SPACE_CMOS: + handler = acpi_ex_cmos_space_handler; + setup = acpi_ev_cmos_region_setup; + break; + + case ACPI_ADR_SPACE_PCI_BAR_TARGET: + handler = acpi_ex_pci_bar_space_handler; + setup = acpi_ev_pci_bar_region_setup; + break; + + case ACPI_ADR_SPACE_DATA_TABLE: + handler = acpi_ex_data_table_space_handler; + setup = NULL; + break; + + default: + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } + + /* If the caller hasn't specified a setup routine, use the default */ + + if (!setup) { + setup = acpi_ev_default_region_setup; + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + /* + * The attached device object already exists. Make sure the handler + * is not already installed. + */ + handler_obj = obj_desc->device.handler; + + /* Walk the handler list for this device */ + + while (handler_obj) { + + /* Same space_id indicates a handler already installed */ + + if (handler_obj->address_space.space_id == space_id) { + if (handler_obj->address_space.handler == + handler) { + /* + * It is (relatively) OK to attempt to install the SAME + * handler twice. This can easily happen with the + * PCI_Config space. + */ + status = AE_SAME_HANDLER; + goto unlock_and_exit; + } else { + /* A handler is already installed */ + + status = AE_ALREADY_EXISTS; + } + goto unlock_and_exit; + } + + /* Walk the linked list of handlers */ + + handler_obj = handler_obj->address_space.next; + } + } else { + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Creating object on Device %p while installing handler\n", + node)); + + /* obj_desc does not exist, create one */ + + if (node->type == ACPI_TYPE_ANY) { + type = ACPI_TYPE_DEVICE; + } else { + type = node->type; + } + + obj_desc = acpi_ut_create_internal_object(type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init new descriptor */ + + obj_desc->common.type = (u8) type; + + /* Attach the new object to the Node */ + + status = acpi_ns_attach_object(node, obj_desc, type); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", + acpi_ut_get_region_name(space_id), space_id, + acpi_ut_get_node_name(node), node, obj_desc)); + + /* + * Install the handler + * + * At this point there is no existing handler. Just allocate the object + * for the handler and link it into the list. + */ + handler_obj = + acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER); + if (!handler_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init handler obj */ + + handler_obj->address_space.space_id = (u8) space_id; + handler_obj->address_space.handler_flags = flags; + handler_obj->address_space.region_list = NULL; + handler_obj->address_space.node = node; + handler_obj->address_space.handler = handler; + handler_obj->address_space.context = context; + handler_obj->address_space.setup = setup; + + /* Install at head of Device.address_space list */ + + handler_obj->address_space.next = obj_desc->device.handler; + + /* + * The Device object is the first reference on the handler_obj. + * Each region that uses the handler adds a reference. + */ + obj_desc->device.handler = handler_obj; + + /* + * Walk the namespace finding all of the regions this + * handler will manage. + * + * Start at the device and search the branch toward + * the leaf nodes until either the leaf is encountered or + * a device is detected that has an address handler of the + * same type. + * + * In either case, back up and search down the remainder + * of the branch + */ + status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, + acpi_ev_install_handler, handler_obj, + NULL); + + unlock_and_exit: + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_execute_reg_methods + * + * PARAMETERS: Node - Namespace node for the device + * space_id - The address space ID + * + * RETURN: Status + * + * DESCRIPTION: Run all _REG methods for the input Space ID; + * Note: assumes namespace is locked, or system init time. + * + ******************************************************************************/ + +acpi_status +acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, + acpi_adr_space_type space_id) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_execute_reg_methods); + + /* + * Run all _REG methods for all Operation Regions for this space ID. This + * is a separate walk in order to handle any interdependencies between + * regions and _REG methods. (i.e. handlers must be installed for all + * regions of this Space ID before we can run any _REG methods) + */ + status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, + &space_id, NULL); + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_reg_run + * + * PARAMETERS: walk_namespace callback + * + * DESCRIPTION: Run _REG method for region objects of the requested space_iD + * + ******************************************************************************/ + +static acpi_status +acpi_ev_reg_run(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + acpi_adr_space_type space_id; + acpi_status status; + + space_id = *ACPI_CAST_PTR(acpi_adr_space_type, context); + + /* Convert and validate the device handle */ + + node = acpi_ns_map_handle_to_node(obj_handle); + if (!node) { + return (AE_BAD_PARAMETER); + } + + /* + * We only care about regions.and objects that are allowed to have address + * space handlers + */ + if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { + return (AE_OK); + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + + /* No object, just exit */ + + return (AE_OK); + } + + /* Object is a Region */ + + if (obj_desc->region.space_id != space_id) { + + /* This region is for a different address space, just ignore it */ + + return (AE_OK); + } + + status = acpi_ev_execute_reg_method(obj_desc, 1); + return (status); +} diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c new file mode 100644 index 000000000000..1b7f9fdbef15 --- /dev/null +++ b/drivers/acpi/acpica/evrgnini.c @@ -0,0 +1,684 @@ +/****************************************************************************** + * + * Module Name: evrgnini- ACPI address_space (op_region) init + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evrgnini") + +/* Local prototypes */ +static u8 acpi_ev_match_pci_root_bridge(char *id); + +static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); + +/******************************************************************************* + * + * FUNCTION: acpi_ev_system_memory_region_setup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * handler_context - Address space handler context + * region_context - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Setup a system_memory operation region + * + ******************************************************************************/ + +acpi_status +acpi_ev_system_memory_region_setup(acpi_handle handle, + u32 function, + void *handler_context, void **region_context) +{ + union acpi_operand_object *region_desc = + (union acpi_operand_object *)handle; + struct acpi_mem_space_context *local_region_context; + + ACPI_FUNCTION_TRACE(ev_system_memory_region_setup); + + if (function == ACPI_REGION_DEACTIVATE) { + if (*region_context) { + local_region_context = + (struct acpi_mem_space_context *)*region_context; + + /* Delete a cached mapping if present */ + + if (local_region_context->mapped_length) { + acpi_os_unmap_memory(local_region_context-> + mapped_logical_address, + local_region_context-> + mapped_length); + } + ACPI_FREE(local_region_context); + *region_context = NULL; + } + return_ACPI_STATUS(AE_OK); + } + + /* Create a new context */ + + local_region_context = + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); + if (!(local_region_context)) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Save the region length and address for use in the handler */ + + local_region_context->length = region_desc->region.length; + local_region_context->address = region_desc->region.address; + + *region_context = local_region_context; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_io_space_region_setup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * handler_context - Address space handler context + * region_context - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Setup a IO operation region + * + ******************************************************************************/ + +acpi_status +acpi_ev_io_space_region_setup(acpi_handle handle, + u32 function, + void *handler_context, void **region_context) +{ + ACPI_FUNCTION_TRACE(ev_io_space_region_setup); + + if (function == ACPI_REGION_DEACTIVATE) { + *region_context = NULL; + } else { + *region_context = handler_context; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_pci_config_region_setup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * handler_context - Address space handler context + * region_context - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Setup a PCI_Config operation region + * + * MUTEX: Assumes namespace is not locked + * + ******************************************************************************/ + +acpi_status +acpi_ev_pci_config_region_setup(acpi_handle handle, + u32 function, + void *handler_context, void **region_context) +{ + acpi_status status = AE_OK; + acpi_integer pci_value; + struct acpi_pci_id *pci_id = *region_context; + union acpi_operand_object *handler_obj; + struct acpi_namespace_node *parent_node; + struct acpi_namespace_node *pci_root_node; + struct acpi_namespace_node *pci_device_node; + union acpi_operand_object *region_obj = + (union acpi_operand_object *)handle; + + ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); + + handler_obj = region_obj->region.handler; + if (!handler_obj) { + /* + * No installed handler. This shouldn't happen because the dispatch + * routine checks before we get here, but we check again just in case. + */ + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Attempting to init a region %p, with no handler\n", + region_obj)); + return_ACPI_STATUS(AE_NOT_EXIST); + } + + *region_context = NULL; + if (function == ACPI_REGION_DEACTIVATE) { + if (pci_id) { + ACPI_FREE(pci_id); + } + return_ACPI_STATUS(status); + } + + parent_node = acpi_ns_get_parent_node(region_obj->region.node); + + /* + * Get the _SEG and _BBN values from the device upon which the handler + * is installed. + * + * We need to get the _SEG and _BBN objects relative to the PCI BUS device. + * This is the device the handler has been registered to handle. + */ + + /* + * If the address_space.Node is still pointing to the root, we need + * to scan upward for a PCI Root bridge and re-associate the op_region + * handlers with that device. + */ + if (handler_obj->address_space.node == acpi_gbl_root_node) { + + /* Start search from the parent object */ + + pci_root_node = parent_node; + while (pci_root_node != acpi_gbl_root_node) { + + /* Get the _HID/_CID in order to detect a root_bridge */ + + if (acpi_ev_is_pci_root_bridge(pci_root_node)) { + + /* Install a handler for this PCI root bridge */ + + status = + acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); + if (ACPI_FAILURE(status)) { + if (status == AE_SAME_HANDLER) { + /* + * It is OK if the handler is already installed on the + * root bridge. Still need to return a context object + * for the new PCI_Config operation region, however. + */ + status = AE_OK; + } else { + ACPI_EXCEPTION((AE_INFO, status, + "Could not install PciConfig handler for Root Bridge %4.4s", + acpi_ut_get_node_name + (pci_root_node))); + } + } + break; + } + + pci_root_node = acpi_ns_get_parent_node(pci_root_node); + } + + /* PCI root bridge not found, use namespace root node */ + } else { + pci_root_node = handler_obj->address_space.node; + } + + /* + * If this region is now initialized, we are done. + * (install_address_space_handler could have initialized it) + */ + if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { + return_ACPI_STATUS(AE_OK); + } + + /* Region is still not initialized. Create a new context */ + + pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id)); + if (!pci_id) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * For PCI_Config space access, we need the segment, bus, device and + * function numbers. Acquire them here. + * + * Find the parent device object. (This allows the operation region to be + * within a subscope under the device, such as a control method.) + */ + pci_device_node = region_obj->region.node; + while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) { + pci_device_node = acpi_ns_get_parent_node(pci_device_node); + } + + if (!pci_device_node) { + ACPI_FREE(pci_id); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* + * Get the PCI device and function numbers from the _ADR object contained + * in the parent's scope. + */ + status = + acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, pci_device_node, + &pci_value); + + /* + * The default is zero, and since the allocation above zeroed the data, + * just do nothing on failure. + */ + if (ACPI_SUCCESS(status)) { + pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value)); + pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value)); + } + + /* The PCI segment number comes from the _SEG method */ + + status = + acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, pci_root_node, + &pci_value); + if (ACPI_SUCCESS(status)) { + pci_id->segment = ACPI_LOWORD(pci_value); + } + + /* The PCI bus number comes from the _BBN method */ + + status = + acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, pci_root_node, + &pci_value); + if (ACPI_SUCCESS(status)) { + pci_id->bus = ACPI_LOWORD(pci_value); + } + + /* Complete this device's pci_id */ + + acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id); + + *region_context = pci_id; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_match_pci_root_bridge + * + * PARAMETERS: Id - The HID/CID in string format + * + * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge + * + * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. + * + ******************************************************************************/ + +static u8 acpi_ev_match_pci_root_bridge(char *id) +{ + + /* + * Check if this is a PCI root. + * ACPI 3.0+: check for a PCI Express root also. + */ + if (!(ACPI_STRNCMP(id, + PCI_ROOT_HID_STRING, + sizeof(PCI_ROOT_HID_STRING))) || + !(ACPI_STRNCMP(id, + PCI_EXPRESS_ROOT_HID_STRING, + sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) { + return (TRUE); + } + + return (FALSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_is_pci_root_bridge + * + * PARAMETERS: Node - Device node being examined + * + * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge + * + * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by + * examining the _HID and _CID for the device. + * + ******************************************************************************/ + +static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) +{ + acpi_status status; + struct acpica_device_id hid; + struct acpi_compatible_id_list *cid; + u32 i; + + /* Get the _HID and check for a PCI Root Bridge */ + + status = acpi_ut_execute_HID(node, &hid); + if (ACPI_FAILURE(status)) { + return (FALSE); + } + + if (acpi_ev_match_pci_root_bridge(hid.value)) { + return (TRUE); + } + + /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */ + + status = acpi_ut_execute_CID(node, &cid); + if (ACPI_FAILURE(status)) { + return (FALSE); + } + + /* Check all _CIDs in the returned list */ + + for (i = 0; i < cid->count; i++) { + if (acpi_ev_match_pci_root_bridge(cid->id[i].value)) { + ACPI_FREE(cid); + return (TRUE); + } + } + + ACPI_FREE(cid); + return (FALSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_pci_bar_region_setup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * handler_context - Address space handler context + * region_context - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Setup a pci_bAR operation region + * + * MUTEX: Assumes namespace is not locked + * + ******************************************************************************/ + +acpi_status +acpi_ev_pci_bar_region_setup(acpi_handle handle, + u32 function, + void *handler_context, void **region_context) +{ + ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_cmos_region_setup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * handler_context - Address space handler context + * region_context - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Setup a CMOS operation region + * + * MUTEX: Assumes namespace is not locked + * + ******************************************************************************/ + +acpi_status +acpi_ev_cmos_region_setup(acpi_handle handle, + u32 function, + void *handler_context, void **region_context) +{ + ACPI_FUNCTION_TRACE(ev_cmos_region_setup); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_default_region_setup + * + * PARAMETERS: Handle - Region we are interested in + * Function - Start or stop + * handler_context - Address space handler context + * region_context - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Default region initialization + * + ******************************************************************************/ + +acpi_status +acpi_ev_default_region_setup(acpi_handle handle, + u32 function, + void *handler_context, void **region_context) +{ + ACPI_FUNCTION_TRACE(ev_default_region_setup); + + if (function == ACPI_REGION_DEACTIVATE) { + *region_context = NULL; + } else { + *region_context = handler_context; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_initialize_region + * + * PARAMETERS: region_obj - Region we are initializing + * acpi_ns_locked - Is namespace locked? + * + * RETURN: Status + * + * DESCRIPTION: Initializes the region, finds any _REG methods and saves them + * for execution at a later time + * + * Get the appropriate address space handler for a newly + * created region. + * + * This also performs address space specific initialization. For + * example, PCI regions must have an _ADR object that contains + * a PCI address in the scope of the definition. This address is + * required to perform an access to PCI config space. + * + * MUTEX: Interpreter should be unlocked, because we may run the _REG + * method for this region. + * + ******************************************************************************/ + +acpi_status +acpi_ev_initialize_region(union acpi_operand_object *region_obj, + u8 acpi_ns_locked) +{ + union acpi_operand_object *handler_obj; + union acpi_operand_object *obj_desc; + acpi_adr_space_type space_id; + struct acpi_namespace_node *node; + acpi_status status; + struct acpi_namespace_node *method_node; + acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG; + union acpi_operand_object *region_obj2; + + ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked); + + if (!region_obj) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) { + return_ACPI_STATUS(AE_OK); + } + + region_obj2 = acpi_ns_get_secondary_object(region_obj); + if (!region_obj2) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + node = acpi_ns_get_parent_node(region_obj->region.node); + space_id = region_obj->region.space_id; + + /* Setup defaults */ + + region_obj->region.handler = NULL; + region_obj2->extra.method_REG = NULL; + region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE); + region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; + + /* Find any "_REG" method associated with this region definition */ + + status = + acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD, + &method_node); + if (ACPI_SUCCESS(status)) { + /* + * The _REG method is optional and there can be only one per region + * definition. This will be executed when the handler is attached + * or removed + */ + region_obj2->extra.method_REG = method_node; + } + + /* + * The following loop depends upon the root Node having no parent + * ie: acpi_gbl_root_node->parent_entry being set to NULL + */ + while (node) { + + /* Check to see if a handler exists */ + + handler_obj = NULL; + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + + /* Can only be a handler if the object exists */ + + switch (node->type) { + case ACPI_TYPE_DEVICE: + + handler_obj = obj_desc->device.handler; + break; + + case ACPI_TYPE_PROCESSOR: + + handler_obj = obj_desc->processor.handler; + break; + + case ACPI_TYPE_THERMAL: + + handler_obj = obj_desc->thermal_zone.handler; + break; + + default: + /* Ignore other objects */ + break; + } + + while (handler_obj) { + + /* Is this handler of the correct type? */ + + if (handler_obj->address_space.space_id == + space_id) { + + /* Found correct handler */ + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Found handler %p for region %p in obj %p\n", + handler_obj, + region_obj, + obj_desc)); + + status = + acpi_ev_attach_region(handler_obj, + region_obj, + acpi_ns_locked); + + /* + * Tell all users that this region is usable by running the _REG + * method + */ + if (acpi_ns_locked) { + status = + acpi_ut_release_mutex + (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS + (status); + } + } + + status = + acpi_ev_execute_reg_method + (region_obj, 1); + + if (acpi_ns_locked) { + status = + acpi_ut_acquire_mutex + (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS + (status); + } + } + + return_ACPI_STATUS(AE_OK); + } + + /* Try next handler in the list */ + + handler_obj = handler_obj->address_space.next; + } + } + + /* This node does not have the handler we need; Pop up one level */ + + node = acpi_ns_get_parent_node(node); + } + + /* If we get here, there is no handler for this region */ + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "No handler for RegionType %s(%X) (RegionObj %p)\n", + acpi_ut_get_region_name(space_id), space_id, + region_obj)); + + return_ACPI_STATUS(AE_NOT_EXIST); +} diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c new file mode 100644 index 000000000000..18dce10c5fb1 --- /dev/null +++ b/drivers/acpi/acpica/evsci.c @@ -0,0 +1,183 @@ +/******************************************************************************* + * + * Module Name: evsci - System Control Interrupt configuration and + * legacy to ACPI mode state transition functions + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evsci") + +/* Local prototypes */ +static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context); + +/******************************************************************************* + * + * FUNCTION: acpi_ev_sci_xrupt_handler + * + * PARAMETERS: Context - Calling Context + * + * RETURN: Status code indicates whether interrupt was handled. + * + * DESCRIPTION: Interrupt handler that will figure out what function or + * control method to call to deal with a SCI. + * + ******************************************************************************/ + +static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) +{ + struct acpi_gpe_xrupt_info *gpe_xrupt_list = context; + u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; + + ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler); + + /* + * We are guaranteed by the ACPI CA initialization/shutdown code that + * if this interrupt handler is installed, ACPI is enabled. + */ + + /* + * Fixed Events: + * Check for and dispatch any Fixed Events that have occurred + */ + interrupt_handled |= acpi_ev_fixed_event_detect(); + + /* + * General Purpose Events: + * Check for and dispatch any GPEs that have occurred + */ + interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); + + return_UINT32(interrupt_handled); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_gpe_xrupt_handler + * + * PARAMETERS: Context - Calling Context + * + * RETURN: Status code indicates whether interrupt was handled. + * + * DESCRIPTION: Handler for GPE Block Device interrupts + * + ******************************************************************************/ + +u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context) +{ + struct acpi_gpe_xrupt_info *gpe_xrupt_list = context; + u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; + + ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler); + + /* + * We are guaranteed by the ACPI CA initialization/shutdown code that + * if this interrupt handler is installed, ACPI is enabled. + */ + + /* GPEs: Check for and dispatch any GPEs that have occurred */ + + interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); + + return_UINT32(interrupt_handled); +} + +/****************************************************************************** + * + * FUNCTION: acpi_ev_install_sci_handler + * + * PARAMETERS: none + * + * RETURN: Status + * + * DESCRIPTION: Installs SCI handler. + * + ******************************************************************************/ + +u32 acpi_ev_install_sci_handler(void) +{ + u32 status = AE_OK; + + ACPI_FUNCTION_TRACE(ev_install_sci_handler); + + status = + acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, + acpi_ev_sci_xrupt_handler, + acpi_gbl_gpe_xrupt_list_head); + return_ACPI_STATUS(status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_ev_remove_sci_handler + * + * PARAMETERS: none + * + * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not + * installed to begin with + * + * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be + * taken. + * + * Note: It doesn't seem important to disable all events or set the event + * enable registers to their original values. The OS should disable + * the SCI interrupt level when the handler is removed, so no more + * events will come in. + * + ******************************************************************************/ + +acpi_status acpi_ev_remove_sci_handler(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_remove_sci_handler); + + /* Just let the OS remove the handler and disable the level */ + + status = + acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, + acpi_ev_sci_xrupt_handler); + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c new file mode 100644 index 000000000000..3b6a069f5b06 --- /dev/null +++ b/drivers/acpi/acpica/evxface.c @@ -0,0 +1,821 @@ +/****************************************************************************** + * + * Module Name: evxface - External interfaces for ACPI events + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evxface") + +/******************************************************************************* + * + * FUNCTION: acpi_install_exception_handler + * + * PARAMETERS: Handler - Pointer to the handler function for the + * event + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function + * + ******************************************************************************/ +#ifdef ACPI_FUTURE_USAGE +acpi_status acpi_install_exception_handler(acpi_exception_handler handler) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_exception_handler); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Don't allow two handlers. */ + + if (acpi_gbl_exception_handler) { + status = AE_ALREADY_EXISTS; + goto cleanup; + } + + /* Install the handler */ + + acpi_gbl_exception_handler = handler; + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) +#endif /* ACPI_FUTURE_USAGE */ +/******************************************************************************* + * + * FUNCTION: acpi_install_fixed_event_handler + * + * PARAMETERS: Event - Event type to enable. + * Handler - Pointer to the handler function for the + * event + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function and then enables the + * event. + * + ******************************************************************************/ +acpi_status +acpi_install_fixed_event_handler(u32 event, + acpi_event_handler handler, void *context) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler); + + /* Parameter validation */ + + if (event > ACPI_EVENT_MAX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Don't allow two handlers. */ + + if (NULL != acpi_gbl_fixed_event_handlers[event].handler) { + status = AE_ALREADY_EXISTS; + goto cleanup; + } + + /* Install the handler before enabling the event */ + + acpi_gbl_fixed_event_handlers[event].handler = handler; + acpi_gbl_fixed_event_handlers[event].context = context; + + status = acpi_clear_event(event); + if (ACPI_SUCCESS(status)) + status = acpi_enable_event(event, 0); + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, "Could not enable fixed event %X", + event)); + + /* Remove the handler */ + + acpi_gbl_fixed_event_handlers[event].handler = NULL; + acpi_gbl_fixed_event_handlers[event].context = NULL; + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Enabled fixed event %X, Handler=%p\n", event, + handler)); + } + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler) + +/******************************************************************************* + * + * FUNCTION: acpi_remove_fixed_event_handler + * + * PARAMETERS: Event - Event type to disable. + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Disables the event and unregisters the event handler. + * + ******************************************************************************/ +acpi_status +acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler); + + /* Parameter validation */ + + if (event > ACPI_EVENT_MAX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Disable the event before removing the handler */ + + status = acpi_disable_event(event, 0); + + /* Always Remove the handler */ + + acpi_gbl_fixed_event_handlers[event].handler = NULL; + acpi_gbl_fixed_event_handlers[event].context = NULL; + + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, + "Could not write to fixed event enable register %X", + event)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n", + event)); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler) + +/******************************************************************************* + * + * FUNCTION: acpi_install_notify_handler + * + * PARAMETERS: Device - The device for which notifies will be handled + * handler_type - The type of handler: + * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) + * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) + * ACPI_ALL_NOTIFY: both system and device + * Handler - Address of the handler + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for notifies on an ACPI device + * + ******************************************************************************/ +acpi_status +acpi_install_notify_handler(acpi_handle device, + u32 handler_type, + acpi_notify_handler handler, void *context) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *notify_obj; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_notify_handler); + + /* Parameter validation */ + + if ((!device) || + (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Convert and validate the device handle */ + + node = acpi_ns_map_handle_to_node(device); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* + * Root Object: + * Registering a notify handler on the root object indicates that the + * caller wishes to receive notifications for all objects. Note that + * only one global handler can be regsitered (per notify type). + */ + if (device == ACPI_ROOT_OBJECT) { + + /* Make sure the handler is not already installed */ + + if (((handler_type & ACPI_SYSTEM_NOTIFY) && + acpi_gbl_system_notify.handler) || + ((handler_type & ACPI_DEVICE_NOTIFY) && + acpi_gbl_device_notify.handler)) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } + + if (handler_type & ACPI_SYSTEM_NOTIFY) { + acpi_gbl_system_notify.node = node; + acpi_gbl_system_notify.handler = handler; + acpi_gbl_system_notify.context = context; + } + + if (handler_type & ACPI_DEVICE_NOTIFY) { + acpi_gbl_device_notify.node = node; + acpi_gbl_device_notify.handler = handler; + acpi_gbl_device_notify.context = context; + } + + /* Global notify handler installed */ + } + + /* + * All Other Objects: + * Caller will only receive notifications specific to the target object. + * Note that only certain object types can receive notifications. + */ + else { + /* Notifies allowed on this object? */ + + if (!acpi_ev_is_notify_object(node)) { + status = AE_TYPE; + goto unlock_and_exit; + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + + /* Object exists - make sure there's no handler */ + + if (((handler_type & ACPI_SYSTEM_NOTIFY) && + obj_desc->common_notify.system_notify) || + ((handler_type & ACPI_DEVICE_NOTIFY) && + obj_desc->common_notify.device_notify)) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } + } else { + /* Create a new object */ + + obj_desc = acpi_ut_create_internal_object(node->type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Attach new object to the Node */ + + status = + acpi_ns_attach_object(device, obj_desc, node->type); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + } + + /* Install the handler */ + + notify_obj = + acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); + if (!notify_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + notify_obj->notify.node = node; + notify_obj->notify.handler = handler; + notify_obj->notify.context = context; + + if (handler_type & ACPI_SYSTEM_NOTIFY) { + obj_desc->common_notify.system_notify = notify_obj; + } + + if (handler_type & ACPI_DEVICE_NOTIFY) { + obj_desc->common_notify.device_notify = notify_obj; + } + + if (handler_type == ACPI_ALL_NOTIFY) { + + /* Extra ref if installed in both */ + + acpi_ut_add_reference(notify_obj); + } + } + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) + +/******************************************************************************* + * + * FUNCTION: acpi_remove_notify_handler + * + * PARAMETERS: Device - The device for which notifies will be handled + * handler_type - The type of handler: + * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) + * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) + * ACPI_ALL_NOTIFY: both system and device + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a handler for notifies on an ACPI device + * + ******************************************************************************/ +acpi_status +acpi_remove_notify_handler(acpi_handle device, + u32 handler_type, acpi_notify_handler handler) +{ + union acpi_operand_object *notify_obj; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); + + /* Parameter validation */ + + if ((!device) || + (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { + status = AE_BAD_PARAMETER; + goto exit; + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Convert and validate the device handle */ + + node = acpi_ns_map_handle_to_node(device); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Root Object */ + + if (device == ACPI_ROOT_OBJECT) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Removing notify handler for namespace root object\n")); + + if (((handler_type & ACPI_SYSTEM_NOTIFY) && + !acpi_gbl_system_notify.handler) || + ((handler_type & ACPI_DEVICE_NOTIFY) && + !acpi_gbl_device_notify.handler)) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + /* Make sure all deferred tasks are completed */ + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + acpi_os_wait_events_complete(NULL); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (handler_type & ACPI_SYSTEM_NOTIFY) { + acpi_gbl_system_notify.node = NULL; + acpi_gbl_system_notify.handler = NULL; + acpi_gbl_system_notify.context = NULL; + } + + if (handler_type & ACPI_DEVICE_NOTIFY) { + acpi_gbl_device_notify.node = NULL; + acpi_gbl_device_notify.handler = NULL; + acpi_gbl_device_notify.context = NULL; + } + } + + /* All Other Objects */ + + else { + /* Notifies allowed on this object? */ + + if (!acpi_ev_is_notify_object(node)) { + status = AE_TYPE; + goto unlock_and_exit; + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + /* Object exists - make sure there's an existing handler */ + + if (handler_type & ACPI_SYSTEM_NOTIFY) { + notify_obj = obj_desc->common_notify.system_notify; + if (!notify_obj) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + if (notify_obj->notify.handler != handler) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + /* Make sure all deferred tasks are completed */ + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + acpi_os_wait_events_complete(NULL); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Remove the handler */ + obj_desc->common_notify.system_notify = NULL; + acpi_ut_remove_reference(notify_obj); + } + + if (handler_type & ACPI_DEVICE_NOTIFY) { + notify_obj = obj_desc->common_notify.device_notify; + if (!notify_obj) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + if (notify_obj->notify.handler != handler) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + /* Make sure all deferred tasks are completed */ + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + acpi_os_wait_events_complete(NULL); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Remove the handler */ + obj_desc->common_notify.device_notify = NULL; + acpi_ut_remove_reference(notify_obj); + } + } + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + exit: + if (ACPI_FAILURE(status)) + ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler")); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) + +/******************************************************************************* + * + * FUNCTION: acpi_install_gpe_handler + * + * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT + * defined GPEs) + * gpe_number - The GPE number within the GPE block + * Type - Whether this GPE should be treated as an + * edge- or level-triggered interrupt. + * Address - Address of the handler + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for a General Purpose Event. + * + ******************************************************************************/ +acpi_status +acpi_install_gpe_handler(acpi_handle gpe_device, + u32 gpe_number, + u32 type, acpi_event_handler address, void *context) +{ + struct acpi_gpe_event_info *gpe_event_info; + struct acpi_handler_info *handler; + acpi_status status; + acpi_cpu_flags flags; + + ACPI_FUNCTION_TRACE(acpi_install_gpe_handler); + + /* Parameter validation */ + + if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) { + status = AE_BAD_PARAMETER; + goto exit; + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Ensure that we have a valid GPE number */ + + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); + if (!gpe_event_info) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Make sure that there isn't a handler there already */ + + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_HANDLER) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } + + /* Allocate and init handler object */ + + handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info)); + if (!handler) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + handler->address = address; + handler->context = context; + handler->method_node = gpe_event_info->dispatch.method_node; + + /* Disable the GPE before installing the handler */ + + status = acpi_ev_disable_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* Install the handler */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + gpe_event_info->dispatch.handler = handler; + + /* Setup up dispatch flags to indicate handler (vs. method) */ + + gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */ + gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER); + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + exit: + if (ACPI_FAILURE(status)) + ACPI_EXCEPTION((AE_INFO, status, + "Installing notify handler failed")); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) + +/******************************************************************************* + * + * FUNCTION: acpi_remove_gpe_handler + * + * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT + * defined GPEs) + * gpe_number - The event to remove a handler + * Address - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a handler for a General Purpose acpi_event. + * + ******************************************************************************/ +acpi_status +acpi_remove_gpe_handler(acpi_handle gpe_device, + u32 gpe_number, acpi_event_handler address) +{ + struct acpi_gpe_event_info *gpe_event_info; + struct acpi_handler_info *handler; + acpi_status status; + acpi_cpu_flags flags; + + ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler); + + /* Parameter validation */ + + if (!address) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Ensure that we have a valid GPE number */ + + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); + if (!gpe_event_info) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Make sure that a handler is indeed installed */ + + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != + ACPI_GPE_DISPATCH_HANDLER) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + /* Make sure that the installed handler is the same */ + + if (gpe_event_info->dispatch.handler->address != address) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Disable the GPE before removing the handler */ + + status = acpi_ev_disable_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* Make sure all deferred tasks are completed */ + + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + acpi_os_wait_events_complete(NULL); + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Remove the handler */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + handler = gpe_event_info->dispatch.handler; + + /* Restore Method node (if any), set dispatch flags */ + + gpe_event_info->dispatch.method_node = handler->method_node; + gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */ + if (handler->method_node) { + gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD; + } + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + + /* Now we can free the handler object */ + + ACPI_FREE(handler); + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) + +/******************************************************************************* + * + * FUNCTION: acpi_acquire_global_lock + * + * PARAMETERS: Timeout - How long the caller is willing to wait + * Handle - Where the handle to the lock is returned + * (if acquired) + * + * RETURN: Status + * + * DESCRIPTION: Acquire the ACPI Global Lock + * + * Note: Allows callers with the same thread ID to acquire the global lock + * multiple times. In other words, externally, the behavior of the global lock + * is identical to an AML mutex. On the first acquire, a new handle is + * returned. On any subsequent calls to acquire by the same thread, the same + * handle is returned. + * + ******************************************************************************/ +acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) +{ + acpi_status status; + + if (!handle) { + return (AE_BAD_PARAMETER); + } + + /* Must lock interpreter to prevent race conditions */ + + acpi_ex_enter_interpreter(); + + status = acpi_ex_acquire_mutex_object(timeout, + acpi_gbl_global_lock_mutex, + acpi_os_get_thread_id()); + + if (ACPI_SUCCESS(status)) { + + /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */ + + *handle = acpi_gbl_global_lock_handle; + } + + acpi_ex_exit_interpreter(); + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock) + +/******************************************************************************* + * + * FUNCTION: acpi_release_global_lock + * + * PARAMETERS: Handle - Returned from acpi_acquire_global_lock + * + * RETURN: Status + * + * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. + * + ******************************************************************************/ +acpi_status acpi_release_global_lock(u32 handle) +{ + acpi_status status; + + if (!handle || (handle != acpi_gbl_global_lock_handle)) { + return (AE_NOT_ACQUIRED); + } + + status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_release_global_lock) diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c new file mode 100644 index 000000000000..f33cc30cb6b8 --- /dev/null +++ b/drivers/acpi/acpica/evxfevnt.c @@ -0,0 +1,871 @@ +/****************************************************************************** + * + * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evxfevnt") + +/* Local prototypes */ +acpi_status +acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, void *context); + +/******************************************************************************* + * + * FUNCTION: acpi_enable + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Transfers the system into ACPI mode. + * + ******************************************************************************/ + +acpi_status acpi_enable(void) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(acpi_enable); + + /* ACPI tables must be present */ + + if (!acpi_tb_tables_loaded()) { + return_ACPI_STATUS(AE_NO_ACPI_TABLES); + } + + /* Check current mode */ + + if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) { + ACPI_DEBUG_PRINT((ACPI_DB_INIT, + "System is already in ACPI mode\n")); + } else { + /* Transition to ACPI mode */ + + status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not transition to ACPI mode")); + return_ACPI_STATUS(status); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INIT, + "Transition to ACPI mode successful\n")); + } + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_enable) + +/******************************************************************************* + * + * FUNCTION: acpi_disable + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode. + * + ******************************************************************************/ +acpi_status acpi_disable(void) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(acpi_disable); + + if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) { + ACPI_DEBUG_PRINT((ACPI_DB_INIT, + "System is already in legacy (non-ACPI) mode\n")); + } else { + /* Transition to LEGACY mode */ + + status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY); + + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not exit ACPI mode to legacy mode")); + return_ACPI_STATUS(status); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n")); + } + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_disable) + +/******************************************************************************* + * + * FUNCTION: acpi_enable_event + * + * PARAMETERS: Event - The fixed eventto be enabled + * Flags - Reserved + * + * RETURN: Status + * + * DESCRIPTION: Enable an ACPI event (fixed) + * + ******************************************************************************/ +acpi_status acpi_enable_event(u32 event, u32 flags) +{ + acpi_status status = AE_OK; + u32 value; + + ACPI_FUNCTION_TRACE(acpi_enable_event); + + /* Decode the Fixed Event */ + + if (event > ACPI_EVENT_MAX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Enable the requested fixed event (by writing a one to the enable + * register bit) + */ + status = + acpi_set_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, 1); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Make sure that the hardware responded */ + + status = + acpi_get_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, &value); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (value != 1) { + ACPI_ERROR((AE_INFO, + "Could not enable %s event", + acpi_ut_get_event_name(event))); + return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); + } + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_enable_event) + +/******************************************************************************* + * + * FUNCTION: acpi_set_gpe_type + * + * PARAMETERS: gpe_device - Parent GPE Device + * gpe_number - GPE level within the GPE block + * Type - New GPE type + * + * RETURN: Status + * + * DESCRIPTION: Set the type of an individual GPE + * + ******************************************************************************/ +acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type) +{ + acpi_status status = AE_OK; + struct acpi_gpe_event_info *gpe_event_info; + + ACPI_FUNCTION_TRACE(acpi_set_gpe_type); + + /* Ensure that we have a valid GPE number */ + + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); + if (!gpe_event_info) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) { + return_ACPI_STATUS(AE_OK); + } + + /* Set the new type (will disable GPE if currently enabled) */ + + status = acpi_ev_set_gpe_type(gpe_event_info, type); + + unlock_and_exit: + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) + +/******************************************************************************* + * + * FUNCTION: acpi_enable_gpe + * + * PARAMETERS: gpe_device - Parent GPE Device + * gpe_number - GPE level within the GPE block + * Flags - Just enable, or also wake enable? + * Called from ISR or not + * + * RETURN: Status + * + * DESCRIPTION: Enable an ACPI event (general purpose) + * + ******************************************************************************/ +acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) +{ + acpi_status status = AE_OK; + acpi_cpu_flags flags; + struct acpi_gpe_event_info *gpe_event_info; + + ACPI_FUNCTION_TRACE(acpi_enable_gpe); + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Ensure that we have a valid GPE number */ + + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); + if (!gpe_event_info) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Perform the enable */ + + status = acpi_ev_enable_gpe(gpe_event_info, TRUE); + + unlock_and_exit: + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_enable_gpe) + +/******************************************************************************* + * + * FUNCTION: acpi_disable_gpe + * + * PARAMETERS: gpe_device - Parent GPE Device + * gpe_number - GPE level within the GPE block + * Flags - Just disable, or also wake disable? + * Called from ISR or not + * + * RETURN: Status + * + * DESCRIPTION: Disable an ACPI event (general purpose) + * + ******************************************************************************/ +acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) +{ + acpi_status status = AE_OK; + acpi_cpu_flags flags; + struct acpi_gpe_event_info *gpe_event_info; + + ACPI_FUNCTION_TRACE(acpi_disable_gpe); + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + /* Ensure that we have a valid GPE number */ + + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); + if (!gpe_event_info) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + status = acpi_ev_disable_gpe(gpe_event_info); + +unlock_and_exit: + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_disable_gpe) + +/******************************************************************************* + * + * FUNCTION: acpi_disable_event + * + * PARAMETERS: Event - The fixed eventto be enabled + * Flags - Reserved + * + * RETURN: Status + * + * DESCRIPTION: Disable an ACPI event (fixed) + * + ******************************************************************************/ +acpi_status acpi_disable_event(u32 event, u32 flags) +{ + acpi_status status = AE_OK; + u32 value; + + ACPI_FUNCTION_TRACE(acpi_disable_event); + + /* Decode the Fixed Event */ + + if (event > ACPI_EVENT_MAX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Disable the requested fixed event (by writing a zero to the enable + * register bit) + */ + status = + acpi_set_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, 0); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = + acpi_get_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, &value); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (value != 0) { + ACPI_ERROR((AE_INFO, + "Could not disable %s events", + acpi_ut_get_event_name(event))); + return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); + } + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_disable_event) + +/******************************************************************************* + * + * FUNCTION: acpi_clear_event + * + * PARAMETERS: Event - The fixed event to be cleared + * + * RETURN: Status + * + * DESCRIPTION: Clear an ACPI event (fixed) + * + ******************************************************************************/ +acpi_status acpi_clear_event(u32 event) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(acpi_clear_event); + + /* Decode the Fixed Event */ + + if (event > ACPI_EVENT_MAX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Clear the requested fixed event (By writing a one to the status + * register bit) + */ + status = + acpi_set_register(acpi_gbl_fixed_event_info[event]. + status_register_id, 1); + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_clear_event) + +/******************************************************************************* + * + * FUNCTION: acpi_clear_gpe + * + * PARAMETERS: gpe_device - Parent GPE Device + * gpe_number - GPE level within the GPE block + * Flags - Called from an ISR or not + * + * RETURN: Status + * + * DESCRIPTION: Clear an ACPI event (general purpose) + * + ******************************************************************************/ +acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) +{ + acpi_status status = AE_OK; + struct acpi_gpe_event_info *gpe_event_info; + + ACPI_FUNCTION_TRACE(acpi_clear_gpe); + + /* Use semaphore lock if not executing at interrupt level */ + + if (flags & ACPI_NOT_ISR) { + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* Ensure that we have a valid GPE number */ + + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); + if (!gpe_event_info) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + status = acpi_hw_clear_gpe(gpe_event_info); + + unlock_and_exit: + if (flags & ACPI_NOT_ISR) { + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + } + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_clear_gpe) +/******************************************************************************* + * + * FUNCTION: acpi_get_event_status + * + * PARAMETERS: Event - The fixed event + * event_status - Where the current status of the event will + * be returned + * + * RETURN: Status + * + * DESCRIPTION: Obtains and returns the current status of the event + * + ******************************************************************************/ +acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) +{ + acpi_status status = AE_OK; + u32 value; + + ACPI_FUNCTION_TRACE(acpi_get_event_status); + + if (!event_status) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Decode the Fixed Event */ + + if (event > ACPI_EVENT_MAX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the status of the requested fixed event */ + + status = + acpi_get_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, &value); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(status); + + *event_status = value; + + status = + acpi_get_register(acpi_gbl_fixed_event_info[event]. + status_register_id, &value); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(status); + + if (value) + *event_status |= ACPI_EVENT_FLAG_SET; + + if (acpi_gbl_fixed_event_handlers[event].handler) + *event_status |= ACPI_EVENT_FLAG_HANDLE; + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_event_status) + +/******************************************************************************* + * + * FUNCTION: acpi_get_gpe_status + * + * PARAMETERS: gpe_device - Parent GPE Device + * gpe_number - GPE level within the GPE block + * Flags - Called from an ISR or not + * event_status - Where the current status of the event will + * be returned + * + * RETURN: Status + * + * DESCRIPTION: Get status of an event (general purpose) + * + ******************************************************************************/ +acpi_status +acpi_get_gpe_status(acpi_handle gpe_device, + u32 gpe_number, u32 flags, acpi_event_status * event_status) +{ + acpi_status status = AE_OK; + struct acpi_gpe_event_info *gpe_event_info; + + ACPI_FUNCTION_TRACE(acpi_get_gpe_status); + + /* Use semaphore lock if not executing at interrupt level */ + + if (flags & ACPI_NOT_ISR) { + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* Ensure that we have a valid GPE number */ + + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); + if (!gpe_event_info) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Obtain status on the requested GPE number */ + + status = acpi_hw_get_gpe_status(gpe_event_info, event_status); + + if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) + *event_status |= ACPI_EVENT_FLAG_HANDLE; + + unlock_and_exit: + if (flags & ACPI_NOT_ISR) { + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + } + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) +/******************************************************************************* + * + * FUNCTION: acpi_install_gpe_block + * + * PARAMETERS: gpe_device - Handle to the parent GPE Block Device + * gpe_block_address - Address and space_iD + * register_count - Number of GPE register pairs in the block + * interrupt_number - H/W interrupt for the block + * + * RETURN: Status + * + * DESCRIPTION: Create and Install a block of GPE registers + * + ******************************************************************************/ +acpi_status +acpi_install_gpe_block(acpi_handle gpe_device, + struct acpi_generic_address *gpe_block_address, + u32 register_count, u32 interrupt_number) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + struct acpi_gpe_block_info *gpe_block; + + ACPI_FUNCTION_TRACE(acpi_install_gpe_block); + + if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + node = acpi_ns_map_handle_to_node(gpe_device); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* + * For user-installed GPE Block Devices, the gpe_block_base_number + * is always zero + */ + status = + acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, + interrupt_number, &gpe_block); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* Run the _PRW methods and enable the GPEs */ + + status = acpi_ev_initialize_gpe_block(node, gpe_block); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* Get the device_object attached to the node */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + + /* No object, create a new one */ + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + status = + acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + } + + /* Install the GPE block in the device_object */ + + obj_desc->device.gpe_block = gpe_block; + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_gpe_block) + +/******************************************************************************* + * + * FUNCTION: acpi_remove_gpe_block + * + * PARAMETERS: gpe_device - Handle to the parent GPE Block Device + * + * RETURN: Status + * + * DESCRIPTION: Remove a previously installed block of GPE registers + * + ******************************************************************************/ +acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + struct acpi_namespace_node *node; + + ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); + + if (!gpe_device) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + node = acpi_ns_map_handle_to_node(gpe_device); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Get the device_object attached to the node */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc || !obj_desc->device.gpe_block) { + return_ACPI_STATUS(AE_NULL_OBJECT); + } + + /* Delete the GPE block (but not the device_object) */ + + status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block); + if (ACPI_SUCCESS(status)) { + obj_desc->device.gpe_block = NULL; + } + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) + +/******************************************************************************* + * + * FUNCTION: acpi_get_gpe_device + * + * PARAMETERS: Index - System GPE index (0-current_gpe_count) + * gpe_device - Where the parent GPE Device is returned + * + * RETURN: Status + * + * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL + * gpe device indicates that the gpe number is contained in one of + * the FADT-defined gpe blocks. Otherwise, the GPE block device. + * + ******************************************************************************/ +acpi_status +acpi_get_gpe_device(u32 index, acpi_handle *gpe_device) +{ + struct acpi_gpe_device_info info; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_get_gpe_device); + + if (!gpe_device) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (index >= acpi_current_gpe_count) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Setup and walk the GPE list */ + + info.index = index; + info.status = AE_NOT_EXIST; + info.gpe_device = NULL; + info.next_block_base_index = 0; + + status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + *gpe_device = info.gpe_device; + return_ACPI_STATUS(info.status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_gpe_device) + +/******************************************************************************* + * + * FUNCTION: acpi_ev_get_gpe_device + * + * PARAMETERS: GPE_WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE + * block device. NULL if the GPE is one of the FADT-defined GPEs. + * + ******************************************************************************/ +acpi_status +acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, void *context) +{ + struct acpi_gpe_device_info *info = context; + + /* Increment Index by the number of GPEs in this block */ + + info->next_block_base_index += + (gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH); + + if (info->index < info->next_block_base_index) { + /* + * The GPE index is within this block, get the node. Leave the node + * NULL for the FADT-defined GPEs + */ + if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) { + info->gpe_device = gpe_block->node; + } + + info->status = AE_OK; + return (AE_CTRL_END); + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_disable_all_gpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Disable and clear all GPEs in all GPE blocks + * + ******************************************************************************/ + +acpi_status acpi_disable_all_gpes(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_disable_all_gpes); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_hw_disable_all_gpes(); + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + + return_ACPI_STATUS(status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_enable_all_runtime_gpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks + * + ******************************************************************************/ + +acpi_status acpi_enable_all_runtime_gpes(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_hw_enable_all_runtime_gpes(); + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c new file mode 100644 index 000000000000..b8633947391b --- /dev/null +++ b/drivers/acpi/acpica/evxfregn.c @@ -0,0 +1,254 @@ +/****************************************************************************** + * + * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and + * Address Spaces. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evxfregn") + +/******************************************************************************* + * + * FUNCTION: acpi_install_address_space_handler + * + * PARAMETERS: Device - Handle for the device + * space_id - The address space ID + * Handler - Address of the handler + * Setup - Address of the setup function + * Context - Value passed to the handler on each access + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for all op_regions of a given space_id. + * + ******************************************************************************/ +acpi_status +acpi_install_address_space_handler(acpi_handle device, + acpi_adr_space_type space_id, + acpi_adr_space_handler handler, + acpi_adr_space_setup setup, void *context) +{ + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_address_space_handler); + + /* Parameter validation */ + + if (!device) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Convert and validate the device handle */ + + node = acpi_ns_map_handle_to_node(device); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Install the handler for all Regions for this Space ID */ + + status = + acpi_ev_install_space_handler(node, space_id, handler, setup, + context); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* Run all _REG methods for this address space */ + + status = acpi_ev_execute_reg_methods(node, space_id); + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler) + +/******************************************************************************* + * + * FUNCTION: acpi_remove_address_space_handler + * + * PARAMETERS: Device - Handle for the device + * space_id - The address space ID + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a previously installed handler. + * + ******************************************************************************/ +acpi_status +acpi_remove_address_space_handler(acpi_handle device, + acpi_adr_space_type space_id, + acpi_adr_space_handler handler) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + union acpi_operand_object *region_obj; + union acpi_operand_object **last_obj_ptr; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler); + + /* Parameter validation */ + + if (!device) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Convert and validate the device handle */ + + node = acpi_ns_map_handle_to_node(device); + if (!node || + ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_PROCESSOR) && + (node->type != ACPI_TYPE_THERMAL) && + (node != acpi_gbl_root_node))) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Make sure the internal object exists */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + /* Find the address handler the user requested */ + + handler_obj = obj_desc->device.handler; + last_obj_ptr = &obj_desc->device.handler; + while (handler_obj) { + + /* We have a handler, see if user requested this one */ + + if (handler_obj->address_space.space_id == space_id) { + + /* Handler must be the same as the installed handler */ + + if (handler_obj->address_space.handler != handler) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Matched space_id, first dereference this in the Regions */ + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Removing address handler %p(%p) for region %s on Device %p(%p)\n", + handler_obj, handler, + acpi_ut_get_region_name(space_id), + node, obj_desc)); + + region_obj = handler_obj->address_space.region_list; + + /* Walk the handler's region list */ + + while (region_obj) { + /* + * First disassociate the handler from the region. + * + * NOTE: this doesn't mean that the region goes away + * The region is just inaccessible as indicated to + * the _REG method + */ + acpi_ev_detach_region(region_obj, TRUE); + + /* + * Walk the list: Just grab the head because the + * detach_region removed the previous head. + */ + region_obj = + handler_obj->address_space.region_list; + + } + + /* Remove this Handler object from the list */ + + *last_obj_ptr = handler_obj->address_space.next; + + /* Now we can delete the handler object */ + + acpi_ut_remove_reference(handler_obj); + goto unlock_and_exit; + } + + /* Walk the linked list of handlers */ + + last_obj_ptr = &handler_obj->address_space.next; + handler_obj = handler_obj->address_space.next; + } + + /* The handler does not exist */ + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n", + handler, acpi_ut_get_region_name(space_id), space_id, + node, obj_desc)); + + status = AE_NOT_EXIST; + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler) diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c new file mode 100644 index 000000000000..be32d0105fe2 --- /dev/null +++ b/drivers/acpi/acpica/exconfig.c @@ -0,0 +1,536 @@ +/****************************************************************************** + * + * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exconfig") + +/* Local prototypes */ +static acpi_status +acpi_ex_add_table(u32 table_index, + struct acpi_namespace_node *parent_node, + union acpi_operand_object **ddb_handle); + +/******************************************************************************* + * + * FUNCTION: acpi_ex_add_table + * + * PARAMETERS: Table - Pointer to raw table + * parent_node - Where to load the table (scope) + * ddb_handle - Where to return the table handle. + * + * RETURN: Status + * + * DESCRIPTION: Common function to Install and Load an ACPI table with a + * returned table handle. + * + ******************************************************************************/ + +static acpi_status +acpi_ex_add_table(u32 table_index, + struct acpi_namespace_node *parent_node, + union acpi_operand_object **ddb_handle) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + + ACPI_FUNCTION_TRACE(ex_add_table); + + /* Create an object to be the table handle */ + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); + if (!obj_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Init the table handle */ + + obj_desc->reference.class = ACPI_REFCLASS_TABLE; + *ddb_handle = obj_desc; + + /* Install the new table into the local data structures */ + + obj_desc->reference.value = table_index; + + /* Add the table to the namespace */ + + status = acpi_ns_load_table(table_index, parent_node); + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(obj_desc); + *ddb_handle = NULL; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_load_table_op + * + * PARAMETERS: walk_state - Current state with operands + * return_desc - Where to store the return object + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table from the RSDT/XSDT + * + ******************************************************************************/ + +acpi_status +acpi_ex_load_table_op(struct acpi_walk_state *walk_state, + union acpi_operand_object **return_desc) +{ + acpi_status status; + union acpi_operand_object **operand = &walk_state->operands[0]; + struct acpi_namespace_node *parent_node; + struct acpi_namespace_node *start_node; + struct acpi_namespace_node *parameter_node = NULL; + union acpi_operand_object *ddb_handle; + struct acpi_table_header *table; + u32 table_index; + + ACPI_FUNCTION_TRACE(ex_load_table_op); + + /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */ + + if ((operand[0]->string.length > ACPI_NAME_SIZE) || + (operand[1]->string.length > ACPI_OEM_ID_SIZE) || + (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Find the ACPI table in the RSDT/XSDT */ + + status = acpi_tb_find_table(operand[0]->string.pointer, + operand[1]->string.pointer, + operand[2]->string.pointer, &table_index); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) { + return_ACPI_STATUS(status); + } + + /* Table not found, return an Integer=0 and AE_OK */ + + ddb_handle = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!ddb_handle) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + ddb_handle->integer.value = 0; + *return_desc = ddb_handle; + + return_ACPI_STATUS(AE_OK); + } + + /* Default nodes */ + + start_node = walk_state->scope_info->scope.node; + parent_node = acpi_gbl_root_node; + + /* root_path (optional parameter) */ + + if (operand[3]->string.length > 0) { + /* + * Find the node referenced by the root_path_string. This is the + * location within the namespace where the table will be loaded. + */ + status = + acpi_ns_get_node(start_node, operand[3]->string.pointer, + ACPI_NS_SEARCH_PARENT, &parent_node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* parameter_path (optional parameter) */ + + if (operand[4]->string.length > 0) { + if ((operand[4]->string.pointer[0] != '\\') && + (operand[4]->string.pointer[0] != '^')) { + /* + * Path is not absolute, so it will be relative to the node + * referenced by the root_path_string (or the NS root if omitted) + */ + start_node = parent_node; + } + + /* Find the node referenced by the parameter_path_string */ + + status = + acpi_ns_get_node(start_node, operand[4]->string.pointer, + ACPI_NS_SEARCH_PARENT, ¶meter_node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* Load the table into the namespace */ + + status = acpi_ex_add_table(table_index, parent_node, &ddb_handle); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Parameter Data (optional) */ + + if (parameter_node) { + + /* Store the parameter data into the optional parameter object */ + + status = acpi_ex_store(operand[5], + ACPI_CAST_PTR(union acpi_operand_object, + parameter_node), + walk_state); + if (ACPI_FAILURE(status)) { + (void)acpi_ex_unload_table(ddb_handle); + return_ACPI_STATUS(status); + } + } + + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_SUCCESS(status)) { + ACPI_INFO((AE_INFO, + "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]", + table->signature, table->oem_id, + table->oem_table_id)); + } + + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, + acpi_gbl_table_handler_context); + } + + *return_desc = ddb_handle; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_load_op + * + * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be + * obtained + * Target - Where a handle to the table will be stored + * walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table from a field or operation region + * + * NOTE: Region Fields (Field, bank_field, index_fields) are resolved to buffer + * objects before this code is reached. + * + * If source is an operation region, it must refer to system_memory, as + * per the ACPI specification. + * + ******************************************************************************/ + +acpi_status +acpi_ex_load_op(union acpi_operand_object *obj_desc, + union acpi_operand_object *target, + struct acpi_walk_state *walk_state) +{ + union acpi_operand_object *ddb_handle; + struct acpi_table_header *table; + struct acpi_table_desc table_desc; + u32 table_index; + acpi_status status; + u32 length; + + ACPI_FUNCTION_TRACE(ex_load_op); + + ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); + + /* Source Object can be either an op_region or a Buffer/Field */ + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_REGION: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Load table from Region %p\n", obj_desc)); + + /* Region must be system_memory (from ACPI spec) */ + + if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* + * If the Region Address and Length have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_region_arguments(obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * Map the table header and get the actual table length. The region + * length is not guaranteed to be the same as the table length. + */ + table = acpi_os_map_memory(obj_desc->region.address, + sizeof(struct acpi_table_header)); + if (!table) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + length = table->length; + acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + + /* Must have at least an ACPI table header */ + + if (length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + /* + * The memory region is not guaranteed to remain stable and we must + * copy the table to a local buffer. For example, the memory region + * is corrupted after suspend on some machines. Dynamically loaded + * tables are usually small, so this overhead is minimal. + */ + + /* Allocate a buffer for the table */ + + table_desc.pointer = ACPI_ALLOCATE(length); + if (!table_desc.pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Map the entire table and copy it */ + + table = acpi_os_map_memory(obj_desc->region.address, length); + if (!table) { + ACPI_FREE(table_desc.pointer); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + ACPI_MEMCPY(table_desc.pointer, table, length); + acpi_os_unmap_memory(table, length); + + table_desc.address = obj_desc->region.address; + break; + + case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Load table from Buffer or Field %p\n", + obj_desc)); + + /* Must have at least an ACPI table header */ + + if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + /* Get the actual table length from the table header */ + + table = + ACPI_CAST_PTR(struct acpi_table_header, + obj_desc->buffer.pointer); + length = table->length; + + /* Table cannot extend beyond the buffer */ + + if (length > obj_desc->buffer.length) { + return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); + } + if (length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + /* + * Copy the table from the buffer because the buffer could be modified + * or even deleted in the future + */ + table_desc.pointer = ACPI_ALLOCATE(length); + if (!table_desc.pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + ACPI_MEMCPY(table_desc.pointer, table, length); + table_desc.address = ACPI_TO_INTEGER(table_desc.pointer); + break; + + default: + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* Validate table checksum (will not get validated in tb_add_table) */ + + status = acpi_tb_verify_checksum(table_desc.pointer, length); + if (ACPI_FAILURE(status)) { + ACPI_FREE(table_desc.pointer); + return_ACPI_STATUS(status); + } + + /* Complete the table descriptor */ + + table_desc.length = length; + table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; + + /* Install the new table into the local data structures */ + + status = acpi_tb_add_table(&table_desc, &table_index); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* + * Add the table to the namespace. + * + * Note: Load the table objects relative to the root of the namespace. + * This appears to go against the ACPI specification, but we do it for + * compatibility with other ACPI implementations. + */ + status = + acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); + if (ACPI_FAILURE(status)) { + + /* On error, table_ptr was deallocated above */ + + return_ACPI_STATUS(status); + } + + /* Store the ddb_handle into the Target operand */ + + status = acpi_ex_store(ddb_handle, target, walk_state); + if (ACPI_FAILURE(status)) { + (void)acpi_ex_unload_table(ddb_handle); + + /* table_ptr was deallocated above */ + + acpi_ut_remove_reference(ddb_handle); + return_ACPI_STATUS(status); + } + + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, + table_desc.pointer, + acpi_gbl_table_handler_context); + } + + cleanup: + if (ACPI_FAILURE(status)) { + + /* Delete allocated table buffer */ + + acpi_tb_delete_table(&table_desc); + } + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_unload_table + * + * PARAMETERS: ddb_handle - Handle to a previously loaded table + * + * RETURN: Status + * + * DESCRIPTION: Unload an ACPI table + * + ******************************************************************************/ + +acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) +{ + acpi_status status = AE_OK; + union acpi_operand_object *table_desc = ddb_handle; + u32 table_index; + struct acpi_table_header *table; + + ACPI_FUNCTION_TRACE(ex_unload_table); + + /* + * Validate the handle + * Although the handle is partially validated in acpi_ex_reconfiguration(), + * when it calls acpi_ex_resolve_operands(), the handle is more completely + * validated here. + */ + if ((!ddb_handle) || + (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) || + (ACPI_GET_OBJECT_TYPE(ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the table index from the ddb_handle */ + + table_index = table_desc->reference.value; + + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_SUCCESS(status)) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, + table, + acpi_gbl_table_handler_context); + } + } + + /* + * Delete the entire namespace under this table Node + * (Offset contains the table_id) + */ + acpi_tb_delete_namespace_by_owner(table_index); + (void)acpi_tb_release_owner_id(table_index); + + acpi_tb_set_table_loaded_flag(table_index, FALSE); + + /* Table unloaded, remove a reference to the ddb_handle object */ + + acpi_ut_remove_reference(ddb_handle); + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c new file mode 100644 index 000000000000..caeead439e8c --- /dev/null +++ b/drivers/acpi/acpica/exconvrt.c @@ -0,0 +1,692 @@ +/****************************************************************************** + * + * Module Name: exconvrt - Object conversion routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exconvrt") + +/* Local prototypes */ +static u32 +acpi_ex_convert_to_ascii(acpi_integer integer, + u16 base, u8 * string, u8 max_length); + +/******************************************************************************* + * + * FUNCTION: acpi_ex_convert_to_integer + * + * PARAMETERS: obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * result_desc - Where the new Integer object is returned + * Flags - Used for string conversion + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to an integer. + * + ******************************************************************************/ + +acpi_status +acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, + union acpi_operand_object **result_desc, u32 flags) +{ + union acpi_operand_object *return_desc; + u8 *pointer; + acpi_integer result; + u32 i; + u32 count; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc); + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_INTEGER: + + /* No conversion necessary */ + + *result_desc = obj_desc; + return_ACPI_STATUS(AE_OK); + + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_STRING: + + /* Note: Takes advantage of common buffer/string fields */ + + pointer = obj_desc->buffer.pointer; + count = obj_desc->buffer.length; + break; + + default: + return_ACPI_STATUS(AE_TYPE); + } + + /* + * Convert the buffer/string to an integer. Note that both buffers and + * strings are treated as raw data - we don't convert ascii to hex for + * strings. + * + * There are two terminating conditions for the loop: + * 1) The size of an integer has been reached, or + * 2) The end of the buffer or string has been reached + */ + result = 0; + + /* String conversion is different than Buffer conversion */ + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_STRING: + + /* + * Convert string to an integer - for most cases, the string must be + * hexadecimal as per the ACPI specification. The only exception (as + * of ACPI 3.0) is that the to_integer() operator allows both decimal + * and hexadecimal strings (hex prefixed with "0x"). + */ + status = acpi_ut_strtoul64((char *)pointer, flags, &result); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + break; + + case ACPI_TYPE_BUFFER: + + /* Check for zero-length buffer */ + + if (!count) { + return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); + } + + /* Transfer no more than an integer's worth of data */ + + if (count > acpi_gbl_integer_byte_width) { + count = acpi_gbl_integer_byte_width; + } + + /* + * Convert buffer to an integer - we simply grab enough raw data + * from the buffer to fill an integer + */ + for (i = 0; i < count; i++) { + /* + * Get next byte and shift it into the Result. + * Little endian is used, meaning that the first byte of the buffer + * is the LSB of the integer + */ + result |= (((acpi_integer) pointer[i]) << (i * 8)); + } + break; + + default: + + /* No other types can get here */ + break; + } + + /* Create a new integer */ + + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(result))); + + /* Save the Result */ + + return_desc->integer.value = result; + acpi_ex_truncate_for32bit_table(return_desc); + *result_desc = return_desc; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_convert_to_buffer + * + * PARAMETERS: obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * result_desc - Where the new buffer object is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to a Buffer + * + ******************************************************************************/ + +acpi_status +acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, + union acpi_operand_object **result_desc) +{ + union acpi_operand_object *return_desc; + u8 *new_buf; + + ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc); + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_BUFFER: + + /* No conversion necessary */ + + *result_desc = obj_desc; + return_ACPI_STATUS(AE_OK); + + case ACPI_TYPE_INTEGER: + + /* + * Create a new Buffer object. + * Need enough space for one integer + */ + return_desc = + acpi_ut_create_buffer_object(acpi_gbl_integer_byte_width); + if (!return_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Copy the integer to the buffer, LSB first */ + + new_buf = return_desc->buffer.pointer; + ACPI_MEMCPY(new_buf, + &obj_desc->integer.value, + acpi_gbl_integer_byte_width); + break; + + case ACPI_TYPE_STRING: + + /* + * Create a new Buffer object + * Size will be the string length + * + * NOTE: Add one to the string length to include the null terminator. + * The ACPI spec is unclear on this subject, but there is existing + * ASL/AML code that depends on the null being transferred to the new + * buffer. + */ + return_desc = acpi_ut_create_buffer_object((acpi_size) + obj_desc->string. + length + 1); + if (!return_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Copy the string to the buffer */ + + new_buf = return_desc->buffer.pointer; + ACPI_STRNCPY((char *)new_buf, (char *)obj_desc->string.pointer, + obj_desc->string.length); + break; + + default: + return_ACPI_STATUS(AE_TYPE); + } + + /* Mark buffer initialized */ + + return_desc->common.flags |= AOPOBJ_DATA_VALID; + *result_desc = return_desc; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_convert_to_ascii + * + * PARAMETERS: Integer - Value to be converted + * Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX + * String - Where the string is returned + * data_width - Size of data item to be converted, in bytes + * + * RETURN: Actual string length + * + * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string + * + ******************************************************************************/ + +static u32 +acpi_ex_convert_to_ascii(acpi_integer integer, + u16 base, u8 * string, u8 data_width) +{ + acpi_integer digit; + u32 i; + u32 j; + u32 k = 0; + u32 hex_length; + u32 decimal_length; + u32 remainder; + u8 supress_zeros; + + ACPI_FUNCTION_ENTRY(); + + switch (base) { + case 10: + + /* Setup max length for the decimal number */ + + switch (data_width) { + case 1: + decimal_length = ACPI_MAX8_DECIMAL_DIGITS; + break; + + case 4: + decimal_length = ACPI_MAX32_DECIMAL_DIGITS; + break; + + case 8: + default: + decimal_length = ACPI_MAX64_DECIMAL_DIGITS; + break; + } + + supress_zeros = TRUE; /* No leading zeros */ + remainder = 0; + + for (i = decimal_length; i > 0; i--) { + + /* Divide by nth factor of 10 */ + + digit = integer; + for (j = 0; j < i; j++) { + (void)acpi_ut_short_divide(digit, 10, &digit, + &remainder); + } + + /* Handle leading zeros */ + + if (remainder != 0) { + supress_zeros = FALSE; + } + + if (!supress_zeros) { + string[k] = (u8) (ACPI_ASCII_ZERO + remainder); + k++; + } + } + break; + + case 16: + + /* hex_length: 2 ascii hex chars per data byte */ + + hex_length = ACPI_MUL_2(data_width); + for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) { + + /* Get one hex digit, most significant digits first */ + + string[k] = + (u8) acpi_ut_hex_to_ascii_char(integer, + ACPI_MUL_4(j)); + k++; + } + break; + + default: + return (0); + } + + /* + * Since leading zeros are suppressed, we must check for the case where + * the integer equals 0 + * + * Finally, null terminate the string and return the length + */ + if (!k) { + string[0] = ACPI_ASCII_ZERO; + k = 1; + } + + string[k] = 0; + return ((u32) k); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_convert_to_string + * + * PARAMETERS: obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * result_desc - Where the string object is returned + * Type - String flags (base and conversion type) + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to a string + * + ******************************************************************************/ + +acpi_status +acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, + union acpi_operand_object ** result_desc, u32 type) +{ + union acpi_operand_object *return_desc; + u8 *new_buf; + u32 i; + u32 string_length = 0; + u16 base = 16; + u8 separator = ','; + + ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc); + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_STRING: + + /* No conversion necessary */ + + *result_desc = obj_desc; + return_ACPI_STATUS(AE_OK); + + case ACPI_TYPE_INTEGER: + + switch (type) { + case ACPI_EXPLICIT_CONVERT_DECIMAL: + + /* Make room for maximum decimal number */ + + string_length = ACPI_MAX_DECIMAL_DIGITS; + base = 10; + break; + + default: + + /* Two hex string characters for each integer byte */ + + string_length = ACPI_MUL_2(acpi_gbl_integer_byte_width); + break; + } + + /* + * Create a new String + * Need enough space for one ASCII integer (plus null terminator) + */ + return_desc = + acpi_ut_create_string_object((acpi_size) string_length); + if (!return_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + new_buf = return_desc->buffer.pointer; + + /* Convert integer to string */ + + string_length = + acpi_ex_convert_to_ascii(obj_desc->integer.value, base, + new_buf, + acpi_gbl_integer_byte_width); + + /* Null terminate at the correct place */ + + return_desc->string.length = string_length; + new_buf[string_length] = 0; + break; + + case ACPI_TYPE_BUFFER: + + /* Setup string length, base, and separator */ + + switch (type) { + case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */ + /* + * From ACPI: "If Data is a buffer, it is converted to a string of + * decimal values separated by commas." + */ + base = 10; + + /* + * Calculate the final string length. Individual string values + * are variable length (include separator for each) + */ + for (i = 0; i < obj_desc->buffer.length; i++) { + if (obj_desc->buffer.pointer[i] >= 100) { + string_length += 4; + } else if (obj_desc->buffer.pointer[i] >= 10) { + string_length += 3; + } else { + string_length += 2; + } + } + break; + + case ACPI_IMPLICIT_CONVERT_HEX: + /* + * From the ACPI spec: + *"The entire contents of the buffer are converted to a string of + * two-character hexadecimal numbers, each separated by a space." + */ + separator = ' '; + string_length = (obj_desc->buffer.length * 3); + break; + + case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string */ + /* + * From ACPI: "If Data is a buffer, it is converted to a string of + * hexadecimal values separated by commas." + */ + string_length = (obj_desc->buffer.length * 3); + break; + + default: + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Create a new string object and string buffer + * (-1 because of extra separator included in string_length from above) + * Allow creation of zero-length strings from zero-length buffers. + */ + if (string_length) { + string_length--; + } + + return_desc = acpi_ut_create_string_object((acpi_size) + string_length); + if (!return_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + new_buf = return_desc->buffer.pointer; + + /* + * Convert buffer bytes to hex or decimal values + * (separated by commas or spaces) + */ + for (i = 0; i < obj_desc->buffer.length; i++) { + new_buf += acpi_ex_convert_to_ascii((acpi_integer) + obj_desc->buffer. + pointer[i], base, + new_buf, 1); + *new_buf++ = separator; /* each separated by a comma or space */ + } + + /* + * Null terminate the string + * (overwrites final comma/space from above) + */ + if (obj_desc->buffer.length) { + new_buf--; + } + *new_buf = 0; + break; + + default: + return_ACPI_STATUS(AE_TYPE); + } + + *result_desc = return_desc; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_convert_to_target_type + * + * PARAMETERS: destination_type - Current type of the destination + * source_desc - Source object to be converted. + * result_desc - Where the converted object is returned + * walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Implements "implicit conversion" rules for storing an object. + * + ******************************************************************************/ + +acpi_status +acpi_ex_convert_to_target_type(acpi_object_type destination_type, + union acpi_operand_object *source_desc, + union acpi_operand_object **result_desc, + struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_convert_to_target_type); + + /* Default behavior */ + + *result_desc = source_desc; + + /* + * If required by the target, + * perform implicit conversion on the source before we store it. + */ + switch (GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args)) { + case ARGI_SIMPLE_TARGET: + case ARGI_FIXED_TARGET: + case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ + + switch (destination_type) { + case ACPI_TYPE_LOCAL_REGION_FIELD: + /* + * Named field can always handle conversions + */ + break; + + default: + /* No conversion allowed for these types */ + + if (destination_type != + ACPI_GET_OBJECT_TYPE(source_desc)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Explicit operator, will store (%s) over existing type (%s)\n", + acpi_ut_get_object_type_name + (source_desc), + acpi_ut_get_type_name + (destination_type))); + status = AE_TYPE; + } + } + break; + + case ARGI_TARGETREF: + + switch (destination_type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + /* + * These types require an Integer operand. We can convert + * a Buffer or a String to an Integer if necessary. + */ + status = + acpi_ex_convert_to_integer(source_desc, result_desc, + 16); + break; + + case ACPI_TYPE_STRING: + /* + * The operand must be a String. We can convert an + * Integer or Buffer if necessary + */ + status = + acpi_ex_convert_to_string(source_desc, result_desc, + ACPI_IMPLICIT_CONVERT_HEX); + break; + + case ACPI_TYPE_BUFFER: + /* + * The operand must be a Buffer. We can convert an + * Integer or String if necessary + */ + status = + acpi_ex_convert_to_buffer(source_desc, result_desc); + break; + + default: + ACPI_ERROR((AE_INFO, + "Bad destination type during conversion: %X", + destination_type)); + status = AE_AML_INTERNAL; + break; + } + break; + + case ARGI_REFERENCE: + /* + * create_xxxx_field cases - we are storing the field object into the name + */ + break; + + default: + ACPI_ERROR((AE_INFO, + "Unknown Target type ID 0x%X AmlOpcode %X DestType %s", + GET_CURRENT_ARG_TYPE(walk_state->op_info-> + runtime_args), + walk_state->opcode, + acpi_ut_get_type_name(destination_type))); + status = AE_AML_INTERNAL; + } + + /* + * Source-to-Target conversion semantics: + * + * If conversion to the target type cannot be performed, then simply + * overwrite the target with the new object and type. + */ + if (status == AE_TYPE) { + status = AE_OK; + } + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c new file mode 100644 index 000000000000..5aa65a214fc2 --- /dev/null +++ b/drivers/acpi/acpica/excreate.c @@ -0,0 +1,522 @@ +/****************************************************************************** + * + * Module Name: excreate - Named object creation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("excreate") +#ifndef ACPI_NO_METHOD_EXECUTION +/******************************************************************************* + * + * FUNCTION: acpi_ex_create_alias + * + * PARAMETERS: walk_state - Current state, contains operands + * + * RETURN: Status + * + * DESCRIPTION: Create a new named alias + * + ******************************************************************************/ +acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) +{ + struct acpi_namespace_node *target_node; + struct acpi_namespace_node *alias_node; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_create_alias); + + /* Get the source/alias operands (both namespace nodes) */ + + alias_node = (struct acpi_namespace_node *)walk_state->operands[0]; + target_node = (struct acpi_namespace_node *)walk_state->operands[1]; + + if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) || + (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { + /* + * Dereference an existing alias so that we don't create a chain + * of aliases. With this code, we guarantee that an alias is + * always exactly one level of indirection away from the + * actual aliased name. + */ + target_node = + ACPI_CAST_PTR(struct acpi_namespace_node, + target_node->object); + } + + /* + * For objects that can never change (i.e., the NS node will + * permanently point to the same object), we can simply attach + * the object to the new NS node. For other objects (such as + * Integers, buffers, etc.), we have to point the Alias node + * to the original Node. + */ + switch (target_node->type) { + + /* For these types, the sub-object can change dynamically via a Store */ + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_BUFFER_FIELD: + + /* + * These types open a new scope, so we need the NS node in order to access + * any children. + */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_LOCAL_SCOPE: + + /* + * The new alias has the type ALIAS and points to the original + * NS node, not the object itself. + */ + alias_node->type = ACPI_TYPE_LOCAL_ALIAS; + alias_node->object = + ACPI_CAST_PTR(union acpi_operand_object, target_node); + break; + + case ACPI_TYPE_METHOD: + + /* + * Control method aliases need to be differentiated + */ + alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; + alias_node->object = + ACPI_CAST_PTR(union acpi_operand_object, target_node); + break; + + default: + + /* Attach the original source object to the new Alias Node */ + + /* + * The new alias assumes the type of the target, and it points + * to the same object. The reference count of the object has an + * additional reference to prevent deletion out from under either the + * target node or the alias Node + */ + status = acpi_ns_attach_object(alias_node, + acpi_ns_get_attached_object + (target_node), + target_node->type); + break; + } + + /* Since both operands are Nodes, we don't need to delete them */ + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_create_event + * + * PARAMETERS: walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new event object + * + ******************************************************************************/ + +acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + + ACPI_FUNCTION_TRACE(ex_create_event); + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Create the actual OS semaphore, with zero initial units -- meaning + * that the event is created in an unsignalled state + */ + status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, + &obj_desc->event.os_semaphore); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Attach object to the Node */ + + status = + acpi_ns_attach_object((struct acpi_namespace_node *)walk_state-> + operands[0], obj_desc, ACPI_TYPE_EVENT); + + cleanup: + /* + * Remove local reference to the object (on error, will cause deletion + * of both object and semaphore if present.) + */ + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_create_mutex + * + * PARAMETERS: walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new mutex object + * + * Mutex (Name[0], sync_level[1]) + * + ******************************************************************************/ + +acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_operand_object *obj_desc; + + ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS); + + /* Create the new mutex object */ + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Create the actual OS Mutex */ + + status = acpi_os_create_mutex(&obj_desc->mutex.os_mutex); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Init object and attach to NS node */ + + obj_desc->mutex.sync_level = + (u8) walk_state->operands[1]->integer.value; + obj_desc->mutex.node = + (struct acpi_namespace_node *)walk_state->operands[0]; + + status = + acpi_ns_attach_object(obj_desc->mutex.node, obj_desc, + ACPI_TYPE_MUTEX); + + cleanup: + /* + * Remove local reference to the object (on error, will cause deletion + * of both object and semaphore if present.) + */ + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_create_region + * + * PARAMETERS: aml_start - Pointer to the region declaration AML + * aml_length - Max length of the declaration AML + * region_space - space_iD for the region + * walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new operation region object + * + ******************************************************************************/ + +acpi_status +acpi_ex_create_region(u8 * aml_start, + u32 aml_length, + u8 region_space, struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + union acpi_operand_object *region_obj2; + + ACPI_FUNCTION_TRACE(ex_create_region); + + /* Get the Namespace Node */ + + node = walk_state->op->common.node; + + /* + * If the region object is already attached to this node, + * just return + */ + if (acpi_ns_get_attached_object(node)) { + return_ACPI_STATUS(AE_OK); + } + + /* + * Space ID must be one of the predefined IDs, or in the user-defined + * range + */ + if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) && + (region_space < ACPI_USER_REGION_BEGIN)) { + ACPI_ERROR((AE_INFO, "Invalid AddressSpace type %X", + region_space)); + return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); + } + + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (%X)\n", + acpi_ut_get_region_name(region_space), region_space)); + + /* Create the region descriptor */ + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Remember location in AML stream of address & length + * operands since they need to be evaluated at run time. + */ + region_obj2 = obj_desc->common.next_object; + region_obj2->extra.aml_start = aml_start; + region_obj2->extra.aml_length = aml_length; + + /* Init the region from the operands */ + + obj_desc->region.space_id = region_space; + obj_desc->region.address = 0; + obj_desc->region.length = 0; + obj_desc->region.node = node; + + /* Install the new region object in the parent Node */ + + status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION); + + cleanup: + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_create_processor + * + * PARAMETERS: walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new processor object and populate the fields + * + * Processor (Name[0], cpu_iD[1], pblock_addr[2], pblock_length[3]) + * + ******************************************************************************/ + +acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state); + + /* Create the processor object */ + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR); + if (!obj_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Initialize the processor object from the operands */ + + obj_desc->processor.proc_id = (u8) operand[1]->integer.value; + obj_desc->processor.length = (u8) operand[3]->integer.value; + obj_desc->processor.address = + (acpi_io_address) operand[2]->integer.value; + + /* Install the processor object in the parent Node */ + + status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], + obj_desc, ACPI_TYPE_PROCESSOR); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_create_power_resource + * + * PARAMETERS: walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new power_resource object and populate the fields + * + * power_resource (Name[0], system_level[1], resource_order[2]) + * + ******************************************************************************/ + +acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + acpi_status status; + union acpi_operand_object *obj_desc; + + ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state); + + /* Create the power resource object */ + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER); + if (!obj_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Initialize the power object from the operands */ + + obj_desc->power_resource.system_level = (u8) operand[1]->integer.value; + obj_desc->power_resource.resource_order = + (u16) operand[2]->integer.value; + + /* Install the power resource object in the parent Node */ + + status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], + obj_desc, ACPI_TYPE_POWER); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ex_create_method + * + * PARAMETERS: aml_start - First byte of the method's AML + * aml_length - AML byte count for this method + * walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Create a new method object + * + ******************************************************************************/ + +acpi_status +acpi_ex_create_method(u8 * aml_start, + u32 aml_length, struct acpi_walk_state *walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *obj_desc; + acpi_status status; + u8 method_flags; + + ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state); + + /* Create a new method object */ + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto exit; + } + + /* Save the method's AML pointer and length */ + + obj_desc->method.aml_start = aml_start; + obj_desc->method.aml_length = aml_length; + + /* + * Disassemble the method flags. Split off the Arg Count + * for efficiency + */ + method_flags = (u8) operand[1]->integer.value; + + obj_desc->method.method_flags = + (u8) (method_flags & ~AML_METHOD_ARG_COUNT); + obj_desc->method.param_count = + (u8) (method_flags & AML_METHOD_ARG_COUNT); + + /* + * Get the sync_level. If method is serialized, a mutex will be + * created for this method when it is parsed. + */ + if (method_flags & AML_METHOD_SERIALIZED) { + /* + * ACPI 1.0: sync_level = 0 + * ACPI 2.0: sync_level = sync_level in method declaration + */ + obj_desc->method.sync_level = (u8) + ((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4); + } + + /* Attach the new object to the method Node */ + + status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], + obj_desc, ACPI_TYPE_METHOD); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + + exit: + /* Remove a reference to the operand */ + + acpi_ut_remove_reference(operand[1]); + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c new file mode 100644 index 000000000000..8241b9eff6c1 --- /dev/null +++ b/drivers/acpi/acpica/exdump.c @@ -0,0 +1,1060 @@ +/****************************************************************************** + * + * Module Name: exdump - Interpreter debug output routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exdump") + +/* + * The following routines are used for debug output only + */ +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/* Local prototypes */ +static void acpi_ex_out_string(char *title, char *value); + +static void acpi_ex_out_pointer(char *title, void *value); + +static void +acpi_ex_dump_object(union acpi_operand_object *obj_desc, + struct acpi_exdump_info *info); + +static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc); + +static void +acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, + u32 level, u32 index); + +/******************************************************************************* + * + * Object Descriptor info tables + * + * Note: The first table entry must be an INIT opcode and must contain + * the table length (number of table entries) + * + ******************************************************************************/ + +static struct acpi_exdump_info acpi_ex_dump_integer[2] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_integer), NULL}, + {ACPI_EXD_UINT64, ACPI_EXD_OFFSET(integer.value), "Value"} +}; + +static struct acpi_exdump_info acpi_ex_dump_string[4] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_string), NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(string.length), "Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(string.pointer), "Pointer"}, + {ACPI_EXD_STRING, 0, NULL} +}; + +static struct acpi_exdump_info acpi_ex_dump_buffer[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer), NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(buffer.length), "Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.pointer), "Pointer"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.node), "Parent Node"}, + {ACPI_EXD_BUFFER, 0, NULL} +}; + +static struct acpi_exdump_info acpi_ex_dump_package[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_package), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(package.flags), "Flags"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(package.count), "Elements"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(package.elements), "Element List"}, + {ACPI_EXD_PACKAGE, 0, NULL} +}; + +static struct acpi_exdump_info acpi_ex_dump_device[4] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_device), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.system_notify), + "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.device_notify), + "Device Notify"} +}; + +static struct acpi_exdump_info acpi_ex_dump_event[2] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_event), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(event.os_semaphore), "OsSemaphore"} +}; + +static struct acpi_exdump_info acpi_ex_dump_method[8] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "ParamCount"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.sync_level), "Sync Level"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.mutex), "Mutex"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.thread_count), "Thread Count"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(method.aml_length), "Aml Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.aml_start), "Aml Start"} +}; + +static struct acpi_exdump_info acpi_ex_dump_mutex[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"}, + {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth), + "Acquire Depth"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"} +}; + +static struct acpi_exdump_info acpi_ex_dump_region[7] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.space_id), "Space Id"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.flags), "Flags"}, + {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(region.address), "Address"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(region.length), "Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.next), "Next"} +}; + +static struct acpi_exdump_info acpi_ex_dump_power[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_power), NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.system_level), + "System Level"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.resource_order), + "Resource Order"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.system_notify), + "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.device_notify), + "Device Notify"} +}; + +static struct acpi_exdump_info acpi_ex_dump_processor[7] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_processor), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.proc_id), "Processor ID"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.length), "Length"}, + {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(processor.address), "Address"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.system_notify), + "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.device_notify), + "Device Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.handler), "Handler"} +}; + +static struct acpi_exdump_info acpi_ex_dump_thermal[4] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_thermal), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.system_notify), + "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.device_notify), + "Device Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.handler), "Handler"} +}; + +static struct acpi_exdump_info acpi_ex_dump_buffer_field[3] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer_field), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer_field.buffer_obj), + "Buffer Object"} +}; + +static struct acpi_exdump_info acpi_ex_dump_region_field[3] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region_field), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"} +}; + +static struct acpi_exdump_info acpi_ex_dump_bank_field[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_bank_field), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(bank_field.value), "Value"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(bank_field.region_obj), + "Region Object"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(bank_field.bank_obj), "Bank Object"} +}; + +static struct acpi_exdump_info acpi_ex_dump_index_field[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_bank_field), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(index_field.value), "Value"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.index_obj), + "Index Object"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.data_obj), "Data Object"} +}; + +static struct acpi_exdump_info acpi_ex_dump_reference[8] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_reference), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.class), "Class"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.value), "Value"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"}, + {ACPI_EXD_REFERENCE, 0, NULL} +}; + +static struct acpi_exdump_info acpi_ex_dump_address_handler[6] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_address_handler), + NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(address_space.space_id), "Space Id"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.next), "Next"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.region_list), + "Region List"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.node), "Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.context), "Context"} +}; + +static struct acpi_exdump_info acpi_ex_dump_notify[3] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_notify), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.node), "Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"} +}; + +/* Miscellaneous tables */ + +static struct acpi_exdump_info acpi_ex_dump_common[4] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_common), NULL}, + {ACPI_EXD_TYPE, 0, NULL}, + {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(common.reference_count), + "Reference Count"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common.flags), "Flags"} +}; + +static struct acpi_exdump_info acpi_ex_dump_field_common[7] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_field_common), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.field_flags), + "Field Flags"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.access_byte_width), + "Access Byte Width"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.bit_length), + "Bit Length"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.start_field_bit_offset), + "Field Bit Offset"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.base_byte_offset), + "Base Byte Offset"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(common_field.node), "Parent Node"} +}; + +static struct acpi_exdump_info acpi_ex_dump_node[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"}, + {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"}, + {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(child), "Child List"}, + {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(peer), "Next Peer"} +}; + +/* Dispatch table, indexed by object type */ + +static struct acpi_exdump_info *acpi_ex_dump_info[] = { + NULL, + acpi_ex_dump_integer, + acpi_ex_dump_string, + acpi_ex_dump_buffer, + acpi_ex_dump_package, + NULL, + acpi_ex_dump_device, + acpi_ex_dump_event, + acpi_ex_dump_method, + acpi_ex_dump_mutex, + acpi_ex_dump_region, + acpi_ex_dump_power, + acpi_ex_dump_processor, + acpi_ex_dump_thermal, + acpi_ex_dump_buffer_field, + NULL, + NULL, + acpi_ex_dump_region_field, + acpi_ex_dump_bank_field, + acpi_ex_dump_index_field, + acpi_ex_dump_reference, + NULL, + NULL, + acpi_ex_dump_notify, + acpi_ex_dump_address_handler, + NULL, + NULL, + NULL +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ex_dump_object + * + * PARAMETERS: obj_desc - Descriptor to dump + * Info - Info table corresponding to this object + * type + * + * RETURN: None + * + * DESCRIPTION: Walk the info table for this object + * + ******************************************************************************/ + +static void +acpi_ex_dump_object(union acpi_operand_object *obj_desc, + struct acpi_exdump_info *info) +{ + u8 *target; + char *name; + u8 count; + + if (!info) { + acpi_os_printf + ("ExDumpObject: Display not implemented for object type %s\n", + acpi_ut_get_object_type_name(obj_desc)); + return; + } + + /* First table entry must contain the table length (# of table entries) */ + + count = info->offset; + + while (count) { + target = ACPI_ADD_PTR(u8, obj_desc, info->offset); + name = info->name; + + switch (info->opcode) { + case ACPI_EXD_INIT: + break; + + case ACPI_EXD_TYPE: + acpi_ex_out_string("Type", + acpi_ut_get_object_type_name + (obj_desc)); + break; + + case ACPI_EXD_UINT8: + + acpi_os_printf("%20s : %2.2X\n", name, *target); + break; + + case ACPI_EXD_UINT16: + + acpi_os_printf("%20s : %4.4X\n", name, + ACPI_GET16(target)); + break; + + case ACPI_EXD_UINT32: + + acpi_os_printf("%20s : %8.8X\n", name, + ACPI_GET32(target)); + break; + + case ACPI_EXD_UINT64: + + acpi_os_printf("%20s : %8.8X%8.8X\n", "Value", + ACPI_FORMAT_UINT64(ACPI_GET64(target))); + break; + + case ACPI_EXD_POINTER: + case ACPI_EXD_ADDRESS: + + acpi_ex_out_pointer(name, + *ACPI_CAST_PTR(void *, target)); + break; + + case ACPI_EXD_STRING: + + acpi_ut_print_string(obj_desc->string.pointer, + ACPI_UINT8_MAX); + acpi_os_printf("\n"); + break; + + case ACPI_EXD_BUFFER: + + ACPI_DUMP_BUFFER(obj_desc->buffer.pointer, + obj_desc->buffer.length); + break; + + case ACPI_EXD_PACKAGE: + + /* Dump the package contents */ + + acpi_os_printf("\nPackage Contents:\n"); + acpi_ex_dump_package_obj(obj_desc, 0, 0); + break; + + case ACPI_EXD_FIELD: + + acpi_ex_dump_object(obj_desc, + acpi_ex_dump_field_common); + break; + + case ACPI_EXD_REFERENCE: + + acpi_ex_out_string("Class Name", + (char *) + acpi_ut_get_reference_name + (obj_desc)); + acpi_ex_dump_reference_obj(obj_desc); + break; + + default: + acpi_os_printf("**** Invalid table opcode [%X] ****\n", + info->opcode); + return; + } + + info++; + count--; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_dump_operand + * + * PARAMETERS: *obj_desc - Pointer to entry to be dumped + * Depth - Current nesting depth + * + * RETURN: None + * + * DESCRIPTION: Dump an operand object + * + ******************************************************************************/ + +void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) +{ + u32 length; + u32 index; + + ACPI_FUNCTION_NAME(ex_dump_operand) + + if (!((ACPI_LV_EXEC & acpi_dbg_level) + && (_COMPONENT & acpi_dbg_layer))) { + return; + } + + if (!obj_desc) { + + /* This could be a null element of a package */ + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n")); + return; + } + + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p Namespace Node: ", + obj_desc)); + ACPI_DUMP_ENTRY(obj_desc, ACPI_LV_EXEC); + return; + } + + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "%p is not a node or operand object: [%s]\n", + obj_desc, + acpi_ut_get_descriptor_name(obj_desc))); + ACPI_DUMP_BUFFER(obj_desc, sizeof(union acpi_operand_object)); + return; + } + + /* obj_desc is a valid object */ + + if (depth > 0) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%*s[%u] %p ", + depth, " ", depth, obj_desc)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p ", obj_desc)); + } + + /* Decode object type */ + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_LOCAL_REFERENCE: + + acpi_os_printf("Reference: [%s] ", + acpi_ut_get_reference_name(obj_desc)); + + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_DEBUG: + + acpi_os_printf("\n"); + break; + + case ACPI_REFCLASS_INDEX: + + acpi_os_printf("%p\n", obj_desc->reference.object); + break; + + case ACPI_REFCLASS_TABLE: + + acpi_os_printf("Table Index %X\n", + obj_desc->reference.value); + break; + + case ACPI_REFCLASS_REFOF: + + acpi_os_printf("%p [%s]\n", obj_desc->reference.object, + acpi_ut_get_type_name(((union + acpi_operand_object + *) + obj_desc-> + reference. + object)->common. + type)); + break; + + case ACPI_REFCLASS_ARG: + + acpi_os_printf("%X", obj_desc->reference.value); + + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + + /* Value is an Integer */ + + acpi_os_printf(" value is [%8.8X%8.8x]", + ACPI_FORMAT_UINT64(obj_desc-> + integer. + value)); + } + + acpi_os_printf("\n"); + break; + + case ACPI_REFCLASS_LOCAL: + + acpi_os_printf("%X", obj_desc->reference.value); + + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + + /* Value is an Integer */ + + acpi_os_printf(" value is [%8.8X%8.8x]", + ACPI_FORMAT_UINT64(obj_desc-> + integer. + value)); + } + + acpi_os_printf("\n"); + break; + + case ACPI_REFCLASS_NAME: + + acpi_os_printf("- [%4.4s]\n", + obj_desc->reference.node->name.ascii); + break; + + default: /* Unknown reference class */ + + acpi_os_printf("%2.2X\n", obj_desc->reference.class); + break; + } + break; + + case ACPI_TYPE_BUFFER: + + acpi_os_printf("Buffer length %.2X @ %p\n", + obj_desc->buffer.length, + obj_desc->buffer.pointer); + + /* Debug only -- dump the buffer contents */ + + if (obj_desc->buffer.pointer) { + length = obj_desc->buffer.length; + if (length > 128) { + length = 128; + } + + acpi_os_printf + ("Buffer Contents: (displaying length 0x%.2X)\n", + length); + ACPI_DUMP_BUFFER(obj_desc->buffer.pointer, length); + } + break; + + case ACPI_TYPE_INTEGER: + + acpi_os_printf("Integer %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(obj_desc->integer.value)); + break; + + case ACPI_TYPE_PACKAGE: + + acpi_os_printf("Package [Len %X] ElementArray %p\n", + obj_desc->package.count, + obj_desc->package.elements); + + /* + * If elements exist, package element pointer is valid, + * and debug_level exceeds 1, dump package's elements. + */ + if (obj_desc->package.count && + obj_desc->package.elements && acpi_dbg_level > 1) { + for (index = 0; index < obj_desc->package.count; + index++) { + acpi_ex_dump_operand(obj_desc->package. + elements[index], + depth + 1); + } + } + break; + + case ACPI_TYPE_REGION: + + acpi_os_printf("Region %s (%X)", + acpi_ut_get_region_name(obj_desc->region. + space_id), + obj_desc->region.space_id); + + /* + * If the address and length have not been evaluated, + * don't print them. + */ + if (!(obj_desc->region.flags & AOPOBJ_DATA_VALID)) { + acpi_os_printf("\n"); + } else { + acpi_os_printf(" base %8.8X%8.8X Length %X\n", + ACPI_FORMAT_NATIVE_UINT(obj_desc->region. + address), + obj_desc->region.length); + } + break; + + case ACPI_TYPE_STRING: + + acpi_os_printf("String length %X @ %p ", + obj_desc->string.length, + obj_desc->string.pointer); + + acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); + acpi_os_printf("\n"); + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + acpi_os_printf("BankField\n"); + break; + + case ACPI_TYPE_LOCAL_REGION_FIELD: + + acpi_os_printf + ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n", + obj_desc->field.bit_length, + obj_desc->field.access_byte_width, + obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK, + obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK, + obj_desc->field.base_byte_offset, + obj_desc->field.start_field_bit_offset); + + acpi_ex_dump_operand(obj_desc->field.region_obj, depth + 1); + break; + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + acpi_os_printf("IndexField\n"); + break; + + case ACPI_TYPE_BUFFER_FIELD: + + acpi_os_printf("BufferField: %X bits at byte %X bit %X of\n", + obj_desc->buffer_field.bit_length, + obj_desc->buffer_field.base_byte_offset, + obj_desc->buffer_field.start_field_bit_offset); + + if (!obj_desc->buffer_field.buffer_obj) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL*\n")); + } else + if (ACPI_GET_OBJECT_TYPE(obj_desc->buffer_field.buffer_obj) + != ACPI_TYPE_BUFFER) { + acpi_os_printf("*not a Buffer*\n"); + } else { + acpi_ex_dump_operand(obj_desc->buffer_field.buffer_obj, + depth + 1); + } + break; + + case ACPI_TYPE_EVENT: + + acpi_os_printf("Event\n"); + break; + + case ACPI_TYPE_METHOD: + + acpi_os_printf("Method(%X) @ %p:%X\n", + obj_desc->method.param_count, + obj_desc->method.aml_start, + obj_desc->method.aml_length); + break; + + case ACPI_TYPE_MUTEX: + + acpi_os_printf("Mutex\n"); + break; + + case ACPI_TYPE_DEVICE: + + acpi_os_printf("Device\n"); + break; + + case ACPI_TYPE_POWER: + + acpi_os_printf("Power\n"); + break; + + case ACPI_TYPE_PROCESSOR: + + acpi_os_printf("Processor\n"); + break; + + case ACPI_TYPE_THERMAL: + + acpi_os_printf("Thermal\n"); + break; + + default: + /* Unknown Type */ + + acpi_os_printf("Unknown Type %X\n", + ACPI_GET_OBJECT_TYPE(obj_desc)); + break; + } + + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_dump_operands + * + * PARAMETERS: Operands - A list of Operand objects + * opcode_name - AML opcode name + * num_operands - Operand count for this opcode + * + * DESCRIPTION: Dump the operands associated with the opcode + * + ******************************************************************************/ + +void +acpi_ex_dump_operands(union acpi_operand_object **operands, + const char *opcode_name, u32 num_operands) +{ + ACPI_FUNCTION_NAME(ex_dump_operands); + + if (!opcode_name) { + opcode_name = "UNKNOWN"; + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "**** Start operand dump for opcode [%s], %d operands\n", + opcode_name, num_operands)); + + if (num_operands == 0) { + num_operands = 1; + } + + /* Dump the individual operands */ + + while (num_operands) { + acpi_ex_dump_operand(*operands, 0); + operands++; + num_operands--; + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "**** End operand dump for [%s]\n", opcode_name)); + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_out* functions + * + * PARAMETERS: Title - Descriptive text + * Value - Value to be displayed + * + * DESCRIPTION: Object dump output formatting functions. These functions + * reduce the number of format strings required and keeps them + * all in one place for easy modification. + * + ******************************************************************************/ + +static void acpi_ex_out_string(char *title, char *value) +{ + acpi_os_printf("%20s : %s\n", title, value); +} + +static void acpi_ex_out_pointer(char *title, void *value) +{ + acpi_os_printf("%20s : %p\n", title, value); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_dump_namespace_node + * + * PARAMETERS: Node - Descriptor to dump + * Flags - Force display if TRUE + * + * DESCRIPTION: Dumps the members of the given.Node + * + ******************************************************************************/ + +void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags) +{ + + ACPI_FUNCTION_ENTRY(); + + if (!flags) { + if (!((ACPI_LV_OBJECTS & acpi_dbg_level) + && (_COMPONENT & acpi_dbg_layer))) { + return; + } + } + + acpi_os_printf("%20s : %4.4s\n", "Name", acpi_ut_get_node_name(node)); + acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type)); + acpi_ex_out_pointer("Attached Object", + acpi_ns_get_attached_object(node)); + acpi_ex_out_pointer("Parent", acpi_ns_get_parent_node(node)); + + acpi_ex_dump_object(ACPI_CAST_PTR(union acpi_operand_object, node), + acpi_ex_dump_node); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_dump_reference_obj + * + * PARAMETERS: Object - Descriptor to dump + * + * DESCRIPTION: Dumps a reference object + * + ******************************************************************************/ + +static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) +{ + struct acpi_buffer ret_buf; + acpi_status status; + + ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; + + if (obj_desc->reference.class == ACPI_REFCLASS_NAME) { + acpi_os_printf(" %p ", obj_desc->reference.node); + + status = + acpi_ns_handle_to_pathname(obj_desc->reference.node, + &ret_buf); + if (ACPI_FAILURE(status)) { + acpi_os_printf(" Could not convert name to pathname\n"); + } else { + acpi_os_printf("%s\n", (char *)ret_buf.pointer); + ACPI_FREE(ret_buf.pointer); + } + } else if (obj_desc->reference.object) { + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == + ACPI_DESC_TYPE_OPERAND) { + acpi_os_printf(" Target: %p", + obj_desc->reference.object); + if (obj_desc->reference.class == ACPI_REFCLASS_TABLE) { + acpi_os_printf(" Table Index: %X\n", + obj_desc->reference.value); + } else { + acpi_os_printf(" Target: %p [%s]\n", + obj_desc->reference.object, + acpi_ut_get_type_name(((union + acpi_operand_object + *) + obj_desc-> + reference. + object)-> + common. + type)); + } + } else { + acpi_os_printf(" Target: %p\n", + obj_desc->reference.object); + } + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_dump_package_obj + * + * PARAMETERS: obj_desc - Descriptor to dump + * Level - Indentation Level + * Index - Package index for this object + * + * DESCRIPTION: Dumps the elements of the package + * + ******************************************************************************/ + +static void +acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, + u32 level, u32 index) +{ + u32 i; + + /* Indentation and index output */ + + if (level > 0) { + for (i = 0; i < level; i++) { + acpi_os_printf(" "); + } + + acpi_os_printf("[%.2d] ", index); + } + + acpi_os_printf("%p ", obj_desc); + + /* Null package elements are allowed */ + + if (!obj_desc) { + acpi_os_printf("[Null Object]\n"); + return; + } + + /* Packages may only contain a few object types */ + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_INTEGER: + + acpi_os_printf("[Integer] = %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(obj_desc->integer.value)); + break; + + case ACPI_TYPE_STRING: + + acpi_os_printf("[String] Value: "); + for (i = 0; i < obj_desc->string.length; i++) { + acpi_os_printf("%c", obj_desc->string.pointer[i]); + } + acpi_os_printf("\n"); + break; + + case ACPI_TYPE_BUFFER: + + acpi_os_printf("[Buffer] Length %.2X = ", + obj_desc->buffer.length); + if (obj_desc->buffer.length) { + acpi_ut_dump_buffer(ACPI_CAST_PTR + (u8, obj_desc->buffer.pointer), + obj_desc->buffer.length, + DB_DWORD_DISPLAY, _COMPONENT); + } else { + acpi_os_printf("\n"); + } + break; + + case ACPI_TYPE_PACKAGE: + + acpi_os_printf("[Package] Contains %d Elements:\n", + obj_desc->package.count); + + for (i = 0; i < obj_desc->package.count; i++) { + acpi_ex_dump_package_obj(obj_desc->package.elements[i], + level + 1, i); + } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + acpi_os_printf("[Object Reference] Type [%s] %2.2X", + acpi_ut_get_reference_name(obj_desc), + obj_desc->reference.class); + acpi_ex_dump_reference_obj(obj_desc); + break; + + default: + + acpi_os_printf("[Unknown Type] %X\n", + ACPI_GET_OBJECT_TYPE(obj_desc)); + break; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_dump_object_descriptor + * + * PARAMETERS: obj_desc - Descriptor to dump + * Flags - Force display if TRUE + * + * DESCRIPTION: Dumps the members of the object descriptor given. + * + ******************************************************************************/ + +void +acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) +{ + ACPI_FUNCTION_TRACE(ex_dump_object_descriptor); + + if (!obj_desc) { + return_VOID; + } + + if (!flags) { + if (!((ACPI_LV_OBJECTS & acpi_dbg_level) + && (_COMPONENT & acpi_dbg_layer))) { + return_VOID; + } + } + + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) { + acpi_ex_dump_namespace_node((struct acpi_namespace_node *) + obj_desc, flags); + + acpi_os_printf("\nAttached Object (%p):\n", + ((struct acpi_namespace_node *)obj_desc)-> + object); + + acpi_ex_dump_object_descriptor(((struct acpi_namespace_node *) + obj_desc)->object, flags); + return_VOID; + } + + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) { + acpi_os_printf + ("ExDumpObjectDescriptor: %p is not an ACPI operand object: [%s]\n", + obj_desc, acpi_ut_get_descriptor_name(obj_desc)); + return_VOID; + } + + if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) { + return_VOID; + } + + /* Common Fields */ + + acpi_ex_dump_object(obj_desc, acpi_ex_dump_common); + + /* Object-specific fields */ + + acpi_ex_dump_object(obj_desc, acpi_ex_dump_info[obj_desc->common.type]); + return_VOID; +} + +#endif diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c new file mode 100644 index 000000000000..7b6df031039d --- /dev/null +++ b/drivers/acpi/acpica/exfield.c @@ -0,0 +1,340 @@ +/****************************************************************************** + * + * Module Name: exfield - ACPI AML (p-code) execution - field manipulation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exfield") + +/******************************************************************************* + * + * FUNCTION: acpi_ex_read_data_from_field + * + * PARAMETERS: walk_state - Current execution state + * obj_desc - The named field + * ret_buffer_desc - Where the return data object is stored + * + * RETURN: Status + * + * DESCRIPTION: Read from a named field. Returns either an Integer or a + * Buffer, depending on the size of the field. + * + ******************************************************************************/ +acpi_status +acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, + union acpi_operand_object *obj_desc, + union acpi_operand_object **ret_buffer_desc) +{ + acpi_status status; + union acpi_operand_object *buffer_desc; + acpi_size length; + void *buffer; + + ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); + + /* Parameter validation */ + + if (!obj_desc) { + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + if (!ret_buffer_desc) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { + /* + * If the buffer_field arguments have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_buffer_field_arguments(obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + } else + if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) + && (obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_SMBUS)) { + /* + * This is an SMBus read. We must create a buffer to hold the data + * and directly access the region handler. + */ + buffer_desc = + acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE); + if (!buffer_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Lock entire transaction if requested */ + + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + + /* + * Perform the read. + * Note: Smbus protocol value is passed in upper 16-bits of Function + */ + status = acpi_ex_access_region(obj_desc, 0, + ACPI_CAST_PTR(acpi_integer, + buffer_desc-> + buffer.pointer), + ACPI_READ | (obj_desc->field. + attribute << 16)); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); + goto exit; + } + + /* + * Allocate a buffer for the contents of the field. + * + * If the field is larger than the size of an acpi_integer, create + * a BUFFER to hold it. Otherwise, use an INTEGER. This allows + * the use of arithmetic operators on the returned value if the + * field size is equal or smaller than an Integer. + * + * Note: Field.length is in bits. + */ + length = + (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length); + if (length > acpi_gbl_integer_byte_width) { + + /* Field is too large for an Integer, create a Buffer instead */ + + buffer_desc = acpi_ut_create_buffer_object(length); + if (!buffer_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + buffer = buffer_desc->buffer.pointer; + } else { + /* Field will fit within an Integer (normal case) */ + + buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!buffer_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + length = acpi_gbl_integer_byte_width; + buffer_desc->integer.value = 0; + buffer = &buffer_desc->integer.value; + } + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", + obj_desc, ACPI_GET_OBJECT_TYPE(obj_desc), buffer, + (u32) length)); + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", + obj_desc->common_field.bit_length, + obj_desc->common_field.start_field_bit_offset, + obj_desc->common_field.base_byte_offset)); + + /* Lock entire transaction if requested */ + + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + + /* Read from the field */ + + status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); + + exit: + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(buffer_desc); + } else { + *ret_buffer_desc = buffer_desc; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_write_data_to_field + * + * PARAMETERS: source_desc - Contains data to write + * obj_desc - The named field + * result_desc - Where the return value is returned, if any + * + * RETURN: Status + * + * DESCRIPTION: Write to a named field + * + ******************************************************************************/ + +acpi_status +acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, + union acpi_operand_object *obj_desc, + union acpi_operand_object **result_desc) +{ + acpi_status status; + u32 length; + void *buffer; + union acpi_operand_object *buffer_desc; + + ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); + + /* Parameter validation */ + + if (!source_desc || !obj_desc) { + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { + /* + * If the buffer_field arguments have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_buffer_field_arguments(obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + } else + if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) + && (obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_SMBUS)) { + /* + * This is an SMBus write. We will bypass the entire field mechanism + * and handoff the buffer directly to the handler. + * + * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE). + */ + if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) { + ACPI_ERROR((AE_INFO, + "SMBus write requires Buffer, found type %s", + acpi_ut_get_object_type_name(source_desc))); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) { + ACPI_ERROR((AE_INFO, + "SMBus write requires Buffer of length %X, found length %X", + ACPI_SMBUS_BUFFER_SIZE, + source_desc->buffer.length)); + + return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); + } + + buffer_desc = + acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE); + if (!buffer_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + buffer = buffer_desc->buffer.pointer; + ACPI_MEMCPY(buffer, source_desc->buffer.pointer, + ACPI_SMBUS_BUFFER_SIZE); + + /* Lock entire transaction if requested */ + + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + + /* + * Perform the write (returns status and perhaps data in the + * same buffer) + * Note: SMBus protocol type is passed in upper 16-bits of Function. + */ + status = acpi_ex_access_region(obj_desc, 0, + (acpi_integer *) buffer, + ACPI_WRITE | (obj_desc->field. + attribute << 16)); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); + + *result_desc = buffer_desc; + return_ACPI_STATUS(status); + } + + /* Get a pointer to the data to be written */ + + switch (ACPI_GET_OBJECT_TYPE(source_desc)) { + case ACPI_TYPE_INTEGER: + buffer = &source_desc->integer.value; + length = sizeof(source_desc->integer.value); + break; + + case ACPI_TYPE_BUFFER: + buffer = source_desc->buffer.pointer; + length = source_desc->buffer.length; + break; + + case ACPI_TYPE_STRING: + buffer = source_desc->string.pointer; + length = source_desc->string.length; + break; + + default: + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", + source_desc, + acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE + (source_desc)), + ACPI_GET_OBJECT_TYPE(source_desc), buffer, length)); + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", + obj_desc, + acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)), + ACPI_GET_OBJECT_TYPE(obj_desc), + obj_desc->common_field.bit_length, + obj_desc->common_field.start_field_bit_offset, + obj_desc->common_field.base_byte_offset)); + + /* Lock entire transaction if requested */ + + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + + /* Write to the field */ + + status = acpi_ex_insert_into_field(obj_desc, buffer, length); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c new file mode 100644 index 000000000000..33cd17a1064f --- /dev/null +++ b/drivers/acpi/acpica/exfldio.c @@ -0,0 +1,961 @@ +/****************************************************************************** + * + * Module Name: exfldio - Aml Field I/O + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exfldio") + +/* Local prototypes */ +static acpi_status +acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, + u32 field_datum_byte_offset, + acpi_integer * value, u32 read_write); + +static u8 +acpi_ex_register_overflow(union acpi_operand_object *obj_desc, + acpi_integer value); + +static acpi_status +acpi_ex_setup_region(union acpi_operand_object *obj_desc, + u32 field_datum_byte_offset); + +/******************************************************************************* + * + * FUNCTION: acpi_ex_setup_region + * + * PARAMETERS: obj_desc - Field to be read or written + * field_datum_byte_offset - Byte offset of this datum within the + * parent field + * + * RETURN: Status + * + * DESCRIPTION: Common processing for acpi_ex_extract_from_field and + * acpi_ex_insert_into_field. Initialize the Region if necessary and + * validate the request. + * + ******************************************************************************/ + +static acpi_status +acpi_ex_setup_region(union acpi_operand_object *obj_desc, + u32 field_datum_byte_offset) +{ + acpi_status status = AE_OK; + union acpi_operand_object *rgn_desc; + + ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset); + + rgn_desc = obj_desc->common_field.region_obj; + + /* We must have a valid region */ + + if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) { + ACPI_ERROR((AE_INFO, "Needed Region, found type %X (%s)", + ACPI_GET_OBJECT_TYPE(rgn_desc), + acpi_ut_get_object_type_name(rgn_desc))); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* + * If the Region Address and Length have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_region_arguments(rgn_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* Exit if Address/Length have been disallowed by the host OS */ + + if (rgn_desc->common.flags & AOPOBJ_INVALID) { + return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); + } + + /* + * Exit now for SMBus address space, it has a non-linear address space + * and the request cannot be directly validated + */ + if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { + + /* SMBus has a non-linear address space */ + + return_ACPI_STATUS(AE_OK); + } +#ifdef ACPI_UNDER_DEVELOPMENT + /* + * If the Field access is any_acc, we can now compute the optimal + * access (because we know know the length of the parent region) + */ + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } +#endif + + /* + * Validate the request. The entire request from the byte offset for a + * length of one field datum (access width) must fit within the region. + * (Region length is specified in bytes) + */ + if (rgn_desc->region.length < + (obj_desc->common_field.base_byte_offset + + field_datum_byte_offset + + obj_desc->common_field.access_byte_width)) { + if (acpi_gbl_enable_interpreter_slack) { + /* + * Slack mode only: We will go ahead and allow access to this + * field if it is within the region length rounded up to the next + * access width boundary. acpi_size cast for 64-bit compile. + */ + if (ACPI_ROUND_UP(rgn_desc->region.length, + obj_desc->common_field. + access_byte_width) >= + ((acpi_size) obj_desc->common_field. + base_byte_offset + + obj_desc->common_field.access_byte_width + + field_datum_byte_offset)) { + return_ACPI_STATUS(AE_OK); + } + } + + if (rgn_desc->region.length < + obj_desc->common_field.access_byte_width) { + /* + * This is the case where the access_type (acc_word, etc.) is wider + * than the region itself. For example, a region of length one + * byte, and a field with Dword access specified. + */ + ACPI_ERROR((AE_INFO, + "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)", + acpi_ut_get_node_name(obj_desc-> + common_field.node), + obj_desc->common_field.access_byte_width, + acpi_ut_get_node_name(rgn_desc->region. + node), + rgn_desc->region.length)); + } + + /* + * Offset rounded up to next multiple of field width + * exceeds region length, indicate an error + */ + ACPI_ERROR((AE_INFO, + "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)", + acpi_ut_get_node_name(obj_desc->common_field.node), + obj_desc->common_field.base_byte_offset, + field_datum_byte_offset, + obj_desc->common_field.access_byte_width, + acpi_ut_get_node_name(rgn_desc->region.node), + rgn_desc->region.length)); + + return_ACPI_STATUS(AE_AML_REGION_LIMIT); + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_access_region + * + * PARAMETERS: obj_desc - Field to be read + * field_datum_byte_offset - Byte offset of this datum within the + * parent field + * Value - Where to store value (must at least + * the size of acpi_integer) + * Function - Read or Write flag plus other region- + * dependent flags + * + * RETURN: Status + * + * DESCRIPTION: Read or Write a single field datum to an Operation Region. + * + ******************************************************************************/ + +acpi_status +acpi_ex_access_region(union acpi_operand_object *obj_desc, + u32 field_datum_byte_offset, + acpi_integer * value, u32 function) +{ + acpi_status status; + union acpi_operand_object *rgn_desc; + acpi_physical_address address; + + ACPI_FUNCTION_TRACE(ex_access_region); + + /* + * Ensure that the region operands are fully evaluated and verify + * the validity of the request + */ + status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * The physical address of this field datum is: + * + * 1) The base of the region, plus + * 2) The base offset of the field, plus + * 3) The current offset into the field + */ + rgn_desc = obj_desc->common_field.region_obj; + address = rgn_desc->region.address + + obj_desc->common_field.base_byte_offset + field_datum_byte_offset; + + if ((function & ACPI_IO_MASK) == ACPI_READ) { + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]")); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]")); + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, + " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n", + acpi_ut_get_region_name(rgn_desc->region. + space_id), + rgn_desc->region.space_id, + obj_desc->common_field.access_byte_width, + obj_desc->common_field.base_byte_offset, + field_datum_byte_offset, ACPI_CAST_PTR(void, + address))); + + /* Invoke the appropriate address_space/op_region handler */ + + status = acpi_ev_address_space_dispatch(rgn_desc, function, + address, + ACPI_MUL_8(obj_desc-> + common_field. + access_byte_width), + value); + + if (ACPI_FAILURE(status)) { + if (status == AE_NOT_IMPLEMENTED) { + ACPI_ERROR((AE_INFO, + "Region %s(%X) not implemented", + acpi_ut_get_region_name(rgn_desc->region. + space_id), + rgn_desc->region.space_id)); + } else if (status == AE_NOT_EXIST) { + ACPI_ERROR((AE_INFO, + "Region %s(%X) has no handler", + acpi_ut_get_region_name(rgn_desc->region. + space_id), + rgn_desc->region.space_id)); + } + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_register_overflow + * + * PARAMETERS: obj_desc - Register(Field) to be written + * Value - Value to be stored + * + * RETURN: TRUE if value overflows the field, FALSE otherwise + * + * DESCRIPTION: Check if a value is out of range of the field being written. + * Used to check if the values written to Index and Bank registers + * are out of range. Normally, the value is simply truncated + * to fit the field, but this case is most likely a serious + * coding error in the ASL. + * + ******************************************************************************/ + +static u8 +acpi_ex_register_overflow(union acpi_operand_object *obj_desc, + acpi_integer value) +{ + + if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) { + /* + * The field is large enough to hold the maximum integer, so we can + * never overflow it. + */ + return (FALSE); + } + + if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) { + /* + * The Value is larger than the maximum value that can fit into + * the register. + */ + return (TRUE); + } + + /* The Value will fit into the field with no truncation */ + + return (FALSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_field_datum_io + * + * PARAMETERS: obj_desc - Field to be read + * field_datum_byte_offset - Byte offset of this datum within the + * parent field + * Value - Where to store value (must be 64 bits) + * read_write - Read or Write flag + * + * RETURN: Status + * + * DESCRIPTION: Read or Write a single datum of a field. The field_type is + * demultiplexed here to handle the different types of fields + * (buffer_field, region_field, index_field, bank_field) + * + ******************************************************************************/ + +static acpi_status +acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, + u32 field_datum_byte_offset, + acpi_integer * value, u32 read_write) +{ + acpi_status status; + acpi_integer local_value; + + ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset); + + if (read_write == ACPI_READ) { + if (!value) { + local_value = 0; + + /* To support reads without saving return value */ + value = &local_value; + } + + /* Clear the entire return buffer first, [Very Important!] */ + + *value = 0; + } + + /* + * The four types of fields are: + * + * buffer_field - Read/write from/to a Buffer + * region_field - Read/write from/to a Operation Region. + * bank_field - Write to a Bank Register, then read/write from/to an + * operation_region + * index_field - Write to an Index Register, then read/write from/to a + * Data Register + */ + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_BUFFER_FIELD: + /* + * If the buffer_field arguments have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_buffer_field_arguments(obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + if (read_write == ACPI_READ) { + /* + * Copy the data from the source buffer. + * Length is the field width in bytes. + */ + ACPI_MEMCPY(value, + (obj_desc->buffer_field.buffer_obj)->buffer. + pointer + + obj_desc->buffer_field.base_byte_offset + + field_datum_byte_offset, + obj_desc->common_field.access_byte_width); + } else { + /* + * Copy the data to the target buffer. + * Length is the field width in bytes. + */ + ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer. + pointer + + obj_desc->buffer_field.base_byte_offset + + field_datum_byte_offset, value, + obj_desc->common_field.access_byte_width); + } + + status = AE_OK; + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + /* + * Ensure that the bank_value is not beyond the capacity of + * the register + */ + if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj, + (acpi_integer) obj_desc-> + bank_field.value)) { + return_ACPI_STATUS(AE_AML_REGISTER_LIMIT); + } + + /* + * For bank_fields, we must write the bank_value to the bank_register + * (itself a region_field) before we can access the data. + */ + status = + acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj, + &obj_desc->bank_field.value, + sizeof(obj_desc->bank_field. + value)); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Now that the Bank has been selected, fall through to the + * region_field case and write the datum to the Operation Region + */ + + /*lint -fallthrough */ + + case ACPI_TYPE_LOCAL_REGION_FIELD: + /* + * For simple region_fields, we just directly access the owning + * Operation Region. + */ + status = + acpi_ex_access_region(obj_desc, field_datum_byte_offset, + value, read_write); + break; + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + /* + * Ensure that the index_value is not beyond the capacity of + * the register + */ + if (acpi_ex_register_overflow(obj_desc->index_field.index_obj, + (acpi_integer) obj_desc-> + index_field.value)) { + return_ACPI_STATUS(AE_AML_REGISTER_LIMIT); + } + + /* Write the index value to the index_register (itself a region_field) */ + + field_datum_byte_offset += obj_desc->index_field.value; + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Write to Index Register: Value %8.8X\n", + field_datum_byte_offset)); + + status = + acpi_ex_insert_into_field(obj_desc->index_field.index_obj, + &field_datum_byte_offset, + sizeof(field_datum_byte_offset)); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (read_write == ACPI_READ) { + + /* Read the datum from the data_register */ + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Read from Data Register\n")); + + status = + acpi_ex_extract_from_field(obj_desc->index_field. + data_obj, value, + sizeof(acpi_integer)); + } else { + /* Write the datum to the data_register */ + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Write to Data Register: Value %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(*value))); + + status = + acpi_ex_insert_into_field(obj_desc->index_field. + data_obj, value, + sizeof(acpi_integer)); + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %X", + ACPI_GET_OBJECT_TYPE(obj_desc))); + status = AE_AML_INTERNAL; + break; + } + + if (ACPI_SUCCESS(status)) { + if (read_write == ACPI_READ) { + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Value Read %8.8X%8.8X, Width %d\n", + ACPI_FORMAT_UINT64(*value), + obj_desc->common_field. + access_byte_width)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Value Written %8.8X%8.8X, Width %d\n", + ACPI_FORMAT_UINT64(*value), + obj_desc->common_field. + access_byte_width)); + } + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_write_with_update_rule + * + * PARAMETERS: obj_desc - Field to be written + * Mask - bitmask within field datum + * field_value - Value to write + * field_datum_byte_offset - Offset of datum within field + * + * RETURN: Status + * + * DESCRIPTION: Apply the field update rule to a field write + * + ******************************************************************************/ + +acpi_status +acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, + acpi_integer mask, + acpi_integer field_value, + u32 field_datum_byte_offset) +{ + acpi_status status = AE_OK; + acpi_integer merged_value; + acpi_integer current_value; + + ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask); + + /* Start with the new bits */ + + merged_value = field_value; + + /* If the mask is all ones, we don't need to worry about the update rule */ + + if (mask != ACPI_INTEGER_MAX) { + + /* Decode the update rule */ + + switch (obj_desc->common_field. + field_flags & AML_FIELD_UPDATE_RULE_MASK) { + case AML_FIELD_UPDATE_PRESERVE: + /* + * Check if update rule needs to be applied (not if mask is all + * ones) The left shift drops the bits we want to ignore. + */ + if ((~mask << (ACPI_MUL_8(sizeof(mask)) - + ACPI_MUL_8(obj_desc->common_field. + access_byte_width))) != 0) { + /* + * Read the current contents of the byte/word/dword containing + * the field, and merge with the new field value. + */ + status = + acpi_ex_field_datum_io(obj_desc, + field_datum_byte_offset, + ¤t_value, + ACPI_READ); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + merged_value |= (current_value & ~mask); + } + break; + + case AML_FIELD_UPDATE_WRITE_AS_ONES: + + /* Set positions outside the field to all ones */ + + merged_value |= ~mask; + break; + + case AML_FIELD_UPDATE_WRITE_AS_ZEROS: + + /* Set positions outside the field to all zeros */ + + merged_value &= mask; + break; + + default: + + ACPI_ERROR((AE_INFO, + "Unknown UpdateRule value: %X", + (obj_desc->common_field. + field_flags & + AML_FIELD_UPDATE_RULE_MASK))); + return_ACPI_STATUS(AE_AML_OPERAND_VALUE); + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(mask), + field_datum_byte_offset, + obj_desc->common_field.access_byte_width, + ACPI_FORMAT_UINT64(field_value), + ACPI_FORMAT_UINT64(merged_value))); + + /* Write the merged value */ + + status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset, + &merged_value, ACPI_WRITE); + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_extract_from_field + * + * PARAMETERS: obj_desc - Field to be read + * Buffer - Where to store the field data + * buffer_length - Length of Buffer + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the current value of the given field + * + ******************************************************************************/ + +acpi_status +acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, + void *buffer, u32 buffer_length) +{ + acpi_status status; + acpi_integer raw_datum; + acpi_integer merged_datum; + u32 field_offset = 0; + u32 buffer_offset = 0; + u32 buffer_tail_bits; + u32 datum_count; + u32 field_datum_count; + u32 i; + + ACPI_FUNCTION_TRACE(ex_extract_from_field); + + /* Validate target buffer and clear it */ + + if (buffer_length < + ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { + ACPI_ERROR((AE_INFO, + "Field size %X (bits) is too large for buffer (%X)", + obj_desc->common_field.bit_length, buffer_length)); + + return_ACPI_STATUS(AE_BUFFER_OVERFLOW); + } + ACPI_MEMSET(buffer, 0, buffer_length); + + /* Compute the number of datums (access width data items) */ + + datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, + obj_desc->common_field.access_bit_width); + field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + + obj_desc->common_field. + start_field_bit_offset, + obj_desc->common_field. + access_bit_width); + + /* Priming read from the field */ + + status = + acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum, + ACPI_READ); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + merged_datum = + raw_datum >> obj_desc->common_field.start_field_bit_offset; + + /* Read the rest of the field */ + + for (i = 1; i < field_datum_count; i++) { + + /* Get next input datum from the field */ + + field_offset += obj_desc->common_field.access_byte_width; + status = acpi_ex_field_datum_io(obj_desc, field_offset, + &raw_datum, ACPI_READ); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Merge with previous datum if necessary. + * + * Note: Before the shift, check if the shift value will be larger than + * the integer size. If so, there is no need to perform the operation. + * This avoids the differences in behavior between different compilers + * concerning shift values larger than the target data width. + */ + if ((obj_desc->common_field.access_bit_width - + obj_desc->common_field.start_field_bit_offset) < + ACPI_INTEGER_BIT_SIZE) { + merged_datum |= + raw_datum << (obj_desc->common_field. + access_bit_width - + obj_desc->common_field. + start_field_bit_offset); + } + + if (i == datum_count) { + break; + } + + /* Write merged datum to target buffer */ + + ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum, + ACPI_MIN(obj_desc->common_field.access_byte_width, + buffer_length - buffer_offset)); + + buffer_offset += obj_desc->common_field.access_byte_width; + merged_datum = + raw_datum >> obj_desc->common_field.start_field_bit_offset; + } + + /* Mask off any extra bits in the last datum */ + + buffer_tail_bits = obj_desc->common_field.bit_length % + obj_desc->common_field.access_bit_width; + if (buffer_tail_bits) { + merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); + } + + /* Write the last datum to the buffer */ + + ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum, + ACPI_MIN(obj_desc->common_field.access_byte_width, + buffer_length - buffer_offset)); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_insert_into_field + * + * PARAMETERS: obj_desc - Field to be written + * Buffer - Data to be written + * buffer_length - Length of Buffer + * + * RETURN: Status + * + * DESCRIPTION: Store the Buffer contents into the given field + * + ******************************************************************************/ + +acpi_status +acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, + void *buffer, u32 buffer_length) +{ + acpi_status status; + acpi_integer mask; + acpi_integer width_mask; + acpi_integer merged_datum; + acpi_integer raw_datum = 0; + u32 field_offset = 0; + u32 buffer_offset = 0; + u32 buffer_tail_bits; + u32 datum_count; + u32 field_datum_count; + u32 i; + u32 required_length; + void *new_buffer; + + ACPI_FUNCTION_TRACE(ex_insert_into_field); + + /* Validate input buffer */ + + new_buffer = NULL; + required_length = + ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); + /* + * We must have a buffer that is at least as long as the field + * we are writing to. This is because individual fields are + * indivisible and partial writes are not supported -- as per + * the ACPI specification. + */ + if (buffer_length < required_length) { + + /* We need to create a new buffer */ + + new_buffer = ACPI_ALLOCATE_ZEROED(required_length); + if (!new_buffer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Copy the original data to the new buffer, starting + * at Byte zero. All unused (upper) bytes of the + * buffer will be 0. + */ + ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); + buffer = new_buffer; + buffer_length = required_length; + } + + /* + * Create the bitmasks used for bit insertion. + * Note: This if/else is used to bypass compiler differences with the + * shift operator + */ + if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) { + width_mask = ACPI_INTEGER_MAX; + } else { + width_mask = + ACPI_MASK_BITS_ABOVE(obj_desc->common_field. + access_bit_width); + } + + mask = width_mask & + ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset); + + /* Compute the number of datums (access width data items) */ + + datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, + obj_desc->common_field.access_bit_width); + + field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + + obj_desc->common_field. + start_field_bit_offset, + obj_desc->common_field. + access_bit_width); + + /* Get initial Datum from the input buffer */ + + ACPI_MEMCPY(&raw_datum, buffer, + ACPI_MIN(obj_desc->common_field.access_byte_width, + buffer_length - buffer_offset)); + + merged_datum = + raw_datum << obj_desc->common_field.start_field_bit_offset; + + /* Write the entire field */ + + for (i = 1; i < field_datum_count; i++) { + + /* Write merged datum to the target field */ + + merged_datum &= mask; + status = acpi_ex_write_with_update_rule(obj_desc, mask, + merged_datum, + field_offset); + if (ACPI_FAILURE(status)) { + goto exit; + } + + field_offset += obj_desc->common_field.access_byte_width; + + /* + * Start new output datum by merging with previous input datum + * if necessary. + * + * Note: Before the shift, check if the shift value will be larger than + * the integer size. If so, there is no need to perform the operation. + * This avoids the differences in behavior between different compilers + * concerning shift values larger than the target data width. + */ + if ((obj_desc->common_field.access_bit_width - + obj_desc->common_field.start_field_bit_offset) < + ACPI_INTEGER_BIT_SIZE) { + merged_datum = + raw_datum >> (obj_desc->common_field. + access_bit_width - + obj_desc->common_field. + start_field_bit_offset); + } else { + merged_datum = 0; + } + + mask = width_mask; + + if (i == datum_count) { + break; + } + + /* Get the next input datum from the buffer */ + + buffer_offset += obj_desc->common_field.access_byte_width; + ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset, + ACPI_MIN(obj_desc->common_field.access_byte_width, + buffer_length - buffer_offset)); + merged_datum |= + raw_datum << obj_desc->common_field.start_field_bit_offset; + } + + /* Mask off any extra bits in the last datum */ + + buffer_tail_bits = (obj_desc->common_field.bit_length + + obj_desc->common_field.start_field_bit_offset) % + obj_desc->common_field.access_bit_width; + if (buffer_tail_bits) { + mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); + } + + /* Write the last datum to the field */ + + merged_datum &= mask; + status = acpi_ex_write_with_update_rule(obj_desc, + mask, merged_datum, + field_offset); + + exit: + /* Free temporary buffer if we used one */ + + if (new_buffer) { + ACPI_FREE(new_buffer); + } + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c new file mode 100644 index 000000000000..e445463de8a9 --- /dev/null +++ b/drivers/acpi/acpica/exmisc.c @@ -0,0 +1,726 @@ + +/****************************************************************************** + * + * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exmisc") + +/******************************************************************************* + * + * FUNCTION: acpi_ex_get_object_reference + * + * PARAMETERS: obj_desc - Create a reference to this object + * return_desc - Where to store the reference + * walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Obtain and return a "reference" to the target object + * Common code for the ref_of_op and the cond_ref_of_op. + * + ******************************************************************************/ +acpi_status +acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, + union acpi_operand_object **return_desc, + struct acpi_walk_state *walk_state) +{ + union acpi_operand_object *reference_obj; + union acpi_operand_object *referenced_obj; + + ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc); + + *return_desc = NULL; + + switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { + case ACPI_DESC_TYPE_OPERAND: + + if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) { + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* + * Must be a reference to a Local or Arg + */ + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + case ACPI_REFCLASS_DEBUG: + + /* The referenced object is the pseudo-node for the local/arg */ + + referenced_obj = obj_desc->reference.object; + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X", + obj_desc->reference.class)); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + break; + + case ACPI_DESC_TYPE_NAMED: + + /* + * A named reference that has already been resolved to a Node + */ + referenced_obj = obj_desc; + break; + + default: + + ACPI_ERROR((AE_INFO, "Invalid descriptor type %X", + ACPI_GET_DESCRIPTOR_TYPE(obj_desc))); + return_ACPI_STATUS(AE_TYPE); + } + + /* Create a new reference object */ + + reference_obj = + acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); + if (!reference_obj) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + reference_obj->reference.class = ACPI_REFCLASS_REFOF; + reference_obj->reference.object = referenced_obj; + *return_desc = reference_obj; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Object %p Type [%s], returning Reference %p\n", + obj_desc, acpi_ut_get_object_type_name(obj_desc), + *return_desc)); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_concat_template + * + * PARAMETERS: Operand0 - First source object + * Operand1 - Second source object + * actual_return_desc - Where to place the return object + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Concatenate two resource templates + * + ******************************************************************************/ + +acpi_status +acpi_ex_concat_template(union acpi_operand_object *operand0, + union acpi_operand_object *operand1, + union acpi_operand_object **actual_return_desc, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_operand_object *return_desc; + u8 *new_buf; + u8 *end_tag; + acpi_size length0; + acpi_size length1; + acpi_size new_length; + + ACPI_FUNCTION_TRACE(ex_concat_template); + + /* + * Find the end_tag descriptor in each resource template. + * Note1: returned pointers point TO the end_tag, not past it. + * Note2: zero-length buffers are allowed; treated like one end_tag + */ + + /* Get the length of the first resource template */ + + status = acpi_ut_get_resource_end_tag(operand0, &end_tag); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer); + + /* Get the length of the second resource template */ + + status = acpi_ut_get_resource_end_tag(operand1, &end_tag); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer); + + /* Combine both lengths, minimum size will be 2 for end_tag */ + + new_length = length0 + length1 + sizeof(struct aml_resource_end_tag); + + /* Create a new buffer object for the result (with one end_tag) */ + + return_desc = acpi_ut_create_buffer_object(new_length); + if (!return_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Copy the templates to the new buffer, 0 first, then 1 follows. One + * end_tag descriptor is copied from Operand1. + */ + new_buf = return_desc->buffer.pointer; + ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length0); + ACPI_MEMCPY(new_buf + length0, operand1->buffer.pointer, length1); + + /* Insert end_tag and set the checksum to zero, means "ignore checksum" */ + + new_buf[new_length - 1] = 0; + new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1; + + /* Return the completed resource template */ + + *actual_return_desc = return_desc; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_do_concatenate + * + * PARAMETERS: Operand0 - First source object + * Operand1 - Second source object + * actual_return_desc - Where to place the return object + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. + * + ******************************************************************************/ + +acpi_status +acpi_ex_do_concatenate(union acpi_operand_object *operand0, + union acpi_operand_object *operand1, + union acpi_operand_object **actual_return_desc, + struct acpi_walk_state *walk_state) +{ + union acpi_operand_object *local_operand1 = operand1; + union acpi_operand_object *return_desc; + char *new_buf; + acpi_status status; + + ACPI_FUNCTION_TRACE(ex_do_concatenate); + + /* + * Convert the second operand if necessary. The first operand + * determines the type of the second operand, (See the Data Types + * section of the ACPI specification.) Both object types are + * guaranteed to be either Integer/String/Buffer by the operand + * resolution mechanism. + */ + switch (ACPI_GET_OBJECT_TYPE(operand0)) { + case ACPI_TYPE_INTEGER: + status = + acpi_ex_convert_to_integer(operand1, &local_operand1, 16); + break; + + case ACPI_TYPE_STRING: + status = acpi_ex_convert_to_string(operand1, &local_operand1, + ACPI_IMPLICIT_CONVERT_HEX); + break; + + case ACPI_TYPE_BUFFER: + status = acpi_ex_convert_to_buffer(operand1, &local_operand1); + break; + + default: + ACPI_ERROR((AE_INFO, "Invalid object type: %X", + ACPI_GET_OBJECT_TYPE(operand0))); + status = AE_AML_INTERNAL; + } + + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* + * Both operands are now known to be the same object type + * (Both are Integer, String, or Buffer), and we can now perform the + * concatenation. + */ + + /* + * There are three cases to handle: + * + * 1) Two Integers concatenated to produce a new Buffer + * 2) Two Strings concatenated to produce a new String + * 3) Two Buffers concatenated to produce a new Buffer + */ + switch (ACPI_GET_OBJECT_TYPE(operand0)) { + case ACPI_TYPE_INTEGER: + + /* Result of two Integers is a Buffer */ + /* Need enough buffer space for two integers */ + + return_desc = acpi_ut_create_buffer_object((acpi_size) + ACPI_MUL_2 + (acpi_gbl_integer_byte_width)); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + new_buf = (char *)return_desc->buffer.pointer; + + /* Copy the first integer, LSB first */ + + ACPI_MEMCPY(new_buf, &operand0->integer.value, + acpi_gbl_integer_byte_width); + + /* Copy the second integer (LSB first) after the first */ + + ACPI_MEMCPY(new_buf + acpi_gbl_integer_byte_width, + &local_operand1->integer.value, + acpi_gbl_integer_byte_width); + break; + + case ACPI_TYPE_STRING: + + /* Result of two Strings is a String */ + + return_desc = acpi_ut_create_string_object(((acpi_size) + operand0->string. + length + + local_operand1-> + string.length)); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + new_buf = return_desc->string.pointer; + + /* Concatenate the strings */ + + ACPI_STRCPY(new_buf, operand0->string.pointer); + ACPI_STRCPY(new_buf + operand0->string.length, + local_operand1->string.pointer); + break; + + case ACPI_TYPE_BUFFER: + + /* Result of two Buffers is a Buffer */ + + return_desc = acpi_ut_create_buffer_object(((acpi_size) + operand0->buffer. + length + + local_operand1-> + buffer.length)); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + new_buf = (char *)return_desc->buffer.pointer; + + /* Concatenate the buffers */ + + ACPI_MEMCPY(new_buf, operand0->buffer.pointer, + operand0->buffer.length); + ACPI_MEMCPY(new_buf + operand0->buffer.length, + local_operand1->buffer.pointer, + local_operand1->buffer.length); + break; + + default: + + /* Invalid object type, should not happen here */ + + ACPI_ERROR((AE_INFO, "Invalid object type: %X", + ACPI_GET_OBJECT_TYPE(operand0))); + status = AE_AML_INTERNAL; + goto cleanup; + } + + *actual_return_desc = return_desc; + + cleanup: + if (local_operand1 != operand1) { + acpi_ut_remove_reference(local_operand1); + } + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_do_math_op + * + * PARAMETERS: Opcode - AML opcode + * Integer0 - Integer operand #0 + * Integer1 - Integer operand #1 + * + * RETURN: Integer result of the operation + * + * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the + * math functions here is to prevent a lot of pointer dereferencing + * to obtain the operands. + * + ******************************************************************************/ + +acpi_integer +acpi_ex_do_math_op(u16 opcode, acpi_integer integer0, acpi_integer integer1) +{ + + ACPI_FUNCTION_ENTRY(); + + switch (opcode) { + case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ + + return (integer0 + integer1); + + case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ + + return (integer0 & integer1); + + case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ + + return (~(integer0 & integer1)); + + case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ + + return (integer0 | integer1); + + case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ + + return (~(integer0 | integer1)); + + case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ + + return (integer0 ^ integer1); + + case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ + + return (integer0 * integer1); + + case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */ + + /* + * We need to check if the shiftcount is larger than the integer bit + * width since the behavior of this is not well-defined in the C language. + */ + if (integer1 >= acpi_gbl_integer_bit_width) { + return (0); + } + return (integer0 << integer1); + + case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */ + + /* + * We need to check if the shiftcount is larger than the integer bit + * width since the behavior of this is not well-defined in the C language. + */ + if (integer1 >= acpi_gbl_integer_bit_width) { + return (0); + } + return (integer0 >> integer1); + + case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ + + return (integer0 - integer1); + + default: + + return (0); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_do_logical_numeric_op + * + * PARAMETERS: Opcode - AML opcode + * Integer0 - Integer operand #0 + * Integer1 - Integer operand #1 + * logical_result - TRUE/FALSE result of the operation + * + * RETURN: Status + * + * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric + * operators (LAnd and LOr), both operands must be integers. + * + * Note: cleanest machine code seems to be produced by the code + * below, rather than using statements of the form: + * Result = (Integer0 && Integer1); + * + ******************************************************************************/ + +acpi_status +acpi_ex_do_logical_numeric_op(u16 opcode, + acpi_integer integer0, + acpi_integer integer1, u8 * logical_result) +{ + acpi_status status = AE_OK; + u8 local_result = FALSE; + + ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op); + + switch (opcode) { + case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ + + if (integer0 && integer1) { + local_result = TRUE; + } + break; + + case AML_LOR_OP: /* LOr (Integer0, Integer1) */ + + if (integer0 || integer1) { + local_result = TRUE; + } + break; + + default: + status = AE_AML_INTERNAL; + break; + } + + /* Return the logical result and status */ + + *logical_result = local_result; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_do_logical_op + * + * PARAMETERS: Opcode - AML opcode + * Operand0 - operand #0 + * Operand1 - operand #1 + * logical_result - TRUE/FALSE result of the operation + * + * RETURN: Status + * + * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the + * functions here is to prevent a lot of pointer dereferencing + * to obtain the operands and to simplify the generation of the + * logical value. For the Numeric operators (LAnd and LOr), both + * operands must be integers. For the other logical operators, + * operands can be any combination of Integer/String/Buffer. The + * first operand determines the type to which the second operand + * will be converted. + * + * Note: cleanest machine code seems to be produced by the code + * below, rather than using statements of the form: + * Result = (Operand0 == Operand1); + * + ******************************************************************************/ + +acpi_status +acpi_ex_do_logical_op(u16 opcode, + union acpi_operand_object *operand0, + union acpi_operand_object *operand1, u8 * logical_result) +{ + union acpi_operand_object *local_operand1 = operand1; + acpi_integer integer0; + acpi_integer integer1; + u32 length0; + u32 length1; + acpi_status status = AE_OK; + u8 local_result = FALSE; + int compare; + + ACPI_FUNCTION_TRACE(ex_do_logical_op); + + /* + * Convert the second operand if necessary. The first operand + * determines the type of the second operand, (See the Data Types + * section of the ACPI 3.0+ specification.) Both object types are + * guaranteed to be either Integer/String/Buffer by the operand + * resolution mechanism. + */ + switch (ACPI_GET_OBJECT_TYPE(operand0)) { + case ACPI_TYPE_INTEGER: + status = + acpi_ex_convert_to_integer(operand1, &local_operand1, 16); + break; + + case ACPI_TYPE_STRING: + status = acpi_ex_convert_to_string(operand1, &local_operand1, + ACPI_IMPLICIT_CONVERT_HEX); + break; + + case ACPI_TYPE_BUFFER: + status = acpi_ex_convert_to_buffer(operand1, &local_operand1); + break; + + default: + status = AE_AML_INTERNAL; + break; + } + + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* + * Two cases: 1) Both Integers, 2) Both Strings or Buffers + */ + if (ACPI_GET_OBJECT_TYPE(operand0) == ACPI_TYPE_INTEGER) { + /* + * 1) Both operands are of type integer + * Note: local_operand1 may have changed above + */ + integer0 = operand0->integer.value; + integer1 = local_operand1->integer.value; + + switch (opcode) { + case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ + + if (integer0 == integer1) { + local_result = TRUE; + } + break; + + case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ + + if (integer0 > integer1) { + local_result = TRUE; + } + break; + + case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ + + if (integer0 < integer1) { + local_result = TRUE; + } + break; + + default: + status = AE_AML_INTERNAL; + break; + } + } else { + /* + * 2) Both operands are Strings or both are Buffers + * Note: Code below takes advantage of common Buffer/String + * object fields. local_operand1 may have changed above. Use + * memcmp to handle nulls in buffers. + */ + length0 = operand0->buffer.length; + length1 = local_operand1->buffer.length; + + /* Lexicographic compare: compare the data bytes */ + + compare = ACPI_MEMCMP(operand0->buffer.pointer, + local_operand1->buffer.pointer, + (length0 > length1) ? length1 : length0); + + switch (opcode) { + case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ + + /* Length and all bytes must be equal */ + + if ((length0 == length1) && (compare == 0)) { + + /* Length and all bytes match ==> TRUE */ + + local_result = TRUE; + } + break; + + case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ + + if (compare > 0) { + local_result = TRUE; + goto cleanup; /* TRUE */ + } + if (compare < 0) { + goto cleanup; /* FALSE */ + } + + /* Bytes match (to shortest length), compare lengths */ + + if (length0 > length1) { + local_result = TRUE; + } + break; + + case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ + + if (compare > 0) { + goto cleanup; /* FALSE */ + } + if (compare < 0) { + local_result = TRUE; + goto cleanup; /* TRUE */ + } + + /* Bytes match (to shortest length), compare lengths */ + + if (length0 < length1) { + local_result = TRUE; + } + break; + + default: + status = AE_AML_INTERNAL; + break; + } + } + + cleanup: + + /* New object was created if implicit conversion performed - delete */ + + if (local_operand1 != operand1) { + acpi_ut_remove_reference(local_operand1); + } + + /* Return the logical result and status */ + + *logical_result = local_result; + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c new file mode 100644 index 000000000000..f86bcee8d656 --- /dev/null +++ b/drivers/acpi/acpica/exmutex.c @@ -0,0 +1,474 @@ + +/****************************************************************************** + * + * Module Name: exmutex - ASL Mutex Acquire/Release functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exmutex") + +/* Local prototypes */ +static void +acpi_ex_link_mutex(union acpi_operand_object *obj_desc, + struct acpi_thread_state *thread); + +/******************************************************************************* + * + * FUNCTION: acpi_ex_unlink_mutex + * + * PARAMETERS: obj_desc - The mutex to be unlinked + * + * RETURN: None + * + * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list + * + ******************************************************************************/ + +void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc) +{ + struct acpi_thread_state *thread = obj_desc->mutex.owner_thread; + + if (!thread) { + return; + } + + /* Doubly linked list */ + + if (obj_desc->mutex.next) { + (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev; + } + + if (obj_desc->mutex.prev) { + (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next; + } else { + thread->acquired_mutex_list = obj_desc->mutex.next; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_link_mutex + * + * PARAMETERS: obj_desc - The mutex to be linked + * Thread - Current executing thread object + * + * RETURN: None + * + * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk + * + ******************************************************************************/ + +static void +acpi_ex_link_mutex(union acpi_operand_object *obj_desc, + struct acpi_thread_state *thread) +{ + union acpi_operand_object *list_head; + + list_head = thread->acquired_mutex_list; + + /* This object will be the first object in the list */ + + obj_desc->mutex.prev = NULL; + obj_desc->mutex.next = list_head; + + /* Update old first object to point back to this object */ + + if (list_head) { + list_head->mutex.prev = obj_desc; + } + + /* Update list head */ + + thread->acquired_mutex_list = obj_desc; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_acquire_mutex_object + * + * PARAMETERS: time_desc - Timeout in milliseconds + * obj_desc - Mutex object + * Thread - Current thread state + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common + * path that supports multiple acquires by the same thread. + * + * MUTEX: Interpreter must be locked + * + * NOTE: This interface is called from three places: + * 1) From acpi_ex_acquire_mutex, via an AML Acquire() operator + * 2) From acpi_ex_acquire_global_lock when an AML Field access requires the + * global lock + * 3) From the external interface, acpi_acquire_global_lock + * + ******************************************************************************/ + +acpi_status +acpi_ex_acquire_mutex_object(u16 timeout, + union acpi_operand_object *obj_desc, + acpi_thread_id thread_id) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc); + + if (!obj_desc) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Support for multiple acquires by the owning thread */ + + if (obj_desc->mutex.thread_id == thread_id) { + /* + * The mutex is already owned by this thread, just increment the + * acquisition depth + */ + obj_desc->mutex.acquisition_depth++; + return_ACPI_STATUS(AE_OK); + } + + /* Acquire the mutex, wait if necessary. Special case for Global Lock */ + + if (obj_desc == acpi_gbl_global_lock_mutex) { + status = acpi_ev_acquire_global_lock(timeout); + } else { + status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, + timeout); + } + + if (ACPI_FAILURE(status)) { + + /* Includes failure from a timeout on time_desc */ + + return_ACPI_STATUS(status); + } + + /* Acquired the mutex: update mutex object */ + + obj_desc->mutex.thread_id = thread_id; + obj_desc->mutex.acquisition_depth = 1; + obj_desc->mutex.original_sync_level = 0; + obj_desc->mutex.owner_thread = NULL; /* Used only for AML Acquire() */ + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_acquire_mutex + * + * PARAMETERS: time_desc - Timeout integer + * obj_desc - Mutex object + * walk_state - Current method execution state + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex + * + ******************************************************************************/ + +acpi_status +acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, + union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex, obj_desc); + + if (!obj_desc) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Must have a valid thread ID */ + + if (!walk_state->thread) { + ACPI_ERROR((AE_INFO, + "Cannot acquire Mutex [%4.4s], null thread info", + acpi_ut_get_node_name(obj_desc->mutex.node))); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + /* + * Current sync level must be less than or equal to the sync level of the + * mutex. This mechanism provides some deadlock prevention + */ + if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { + ACPI_ERROR((AE_INFO, + "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%d)", + acpi_ut_get_node_name(obj_desc->mutex.node), + walk_state->thread->current_sync_level)); + return_ACPI_STATUS(AE_AML_MUTEX_ORDER); + } + + status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value, + obj_desc, + walk_state->thread->thread_id); + if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) { + + /* Save Thread object, original/current sync levels */ + + obj_desc->mutex.owner_thread = walk_state->thread; + obj_desc->mutex.original_sync_level = + walk_state->thread->current_sync_level; + walk_state->thread->current_sync_level = + obj_desc->mutex.sync_level; + + /* Link the mutex to the current thread for force-unlock at method exit */ + + acpi_ex_link_mutex(obj_desc, walk_state->thread); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_release_mutex_object + * + * PARAMETERS: obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Release a previously acquired Mutex, low level interface. + * Provides a common path that supports multiple releases (after + * previous multiple acquires) by the same thread. + * + * MUTEX: Interpreter must be locked + * + * NOTE: This interface is called from three places: + * 1) From acpi_ex_release_mutex, via an AML Acquire() operator + * 2) From acpi_ex_release_global_lock when an AML Field access requires the + * global lock + * 3) From the external interface, acpi_release_global_lock + * + ******************************************************************************/ + +acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_release_mutex_object); + + if (obj_desc->mutex.acquisition_depth == 0) { + return (AE_NOT_ACQUIRED); + } + + /* Match multiple Acquires with multiple Releases */ + + obj_desc->mutex.acquisition_depth--; + if (obj_desc->mutex.acquisition_depth != 0) { + + /* Just decrement the depth and return */ + + return_ACPI_STATUS(AE_OK); + } + + if (obj_desc->mutex.owner_thread) { + + /* Unlink the mutex from the owner's list */ + + acpi_ex_unlink_mutex(obj_desc); + obj_desc->mutex.owner_thread = NULL; + } + + /* Release the mutex, special case for Global Lock */ + + if (obj_desc == acpi_gbl_global_lock_mutex) { + status = acpi_ev_release_global_lock(); + } else { + acpi_os_release_mutex(obj_desc->mutex.os_mutex); + } + + /* Clear mutex info */ + + obj_desc->mutex.thread_id = NULL; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_release_mutex + * + * PARAMETERS: obj_desc - The object descriptor for this op + * walk_state - Current method execution state + * + * RETURN: Status + * + * DESCRIPTION: Release a previously acquired Mutex. + * + ******************************************************************************/ + +acpi_status +acpi_ex_release_mutex(union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_release_mutex); + + if (!obj_desc) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* The mutex must have been previously acquired in order to release it */ + + if (!obj_desc->mutex.owner_thread) { + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], not acquired", + acpi_ut_get_node_name(obj_desc->mutex.node))); + return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); + } + + /* + * The Mutex is owned, but this thread must be the owner. + * Special case for Global Lock, any thread can release + */ + if ((obj_desc->mutex.owner_thread->thread_id != + walk_state->thread->thread_id) + && (obj_desc != acpi_gbl_global_lock_mutex)) { + ACPI_ERROR((AE_INFO, + "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", + (unsigned long)walk_state->thread->thread_id, + acpi_ut_get_node_name(obj_desc->mutex.node), + (unsigned long)obj_desc->mutex.owner_thread-> + thread_id)); + return_ACPI_STATUS(AE_AML_NOT_OWNER); + } + + /* Must have a valid thread ID */ + + if (!walk_state->thread) { + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], null thread info", + acpi_ut_get_node_name(obj_desc->mutex.node))); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + /* + * The sync level of the mutex must be less than or equal to the current + * sync level + */ + if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %d current %d", + acpi_ut_get_node_name(obj_desc->mutex.node), + obj_desc->mutex.sync_level, + walk_state->thread->current_sync_level)); + return_ACPI_STATUS(AE_AML_MUTEX_ORDER); + } + + status = acpi_ex_release_mutex_object(obj_desc); + + if (obj_desc->mutex.acquisition_depth == 0) { + + /* Restore the original sync_level */ + + walk_state->thread->current_sync_level = + obj_desc->mutex.original_sync_level; + } + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_release_all_mutexes + * + * PARAMETERS: Thread - Current executing thread object + * + * RETURN: Status + * + * DESCRIPTION: Release all mutexes held by this thread + * + * NOTE: This function is called as the thread is exiting the interpreter. + * Mutexes are not released when an individual control method is exited, but + * only when the parent thread actually exits the interpreter. This allows one + * method to acquire a mutex, and a different method to release it, as long as + * this is performed underneath a single parent control method. + * + ******************************************************************************/ + +void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) +{ + union acpi_operand_object *next = thread->acquired_mutex_list; + union acpi_operand_object *obj_desc; + + ACPI_FUNCTION_ENTRY(); + + /* Traverse the list of owned mutexes, releasing each one */ + + while (next) { + obj_desc = next; + next = obj_desc->mutex.next; + + obj_desc->mutex.prev = NULL; + obj_desc->mutex.next = NULL; + obj_desc->mutex.acquisition_depth = 0; + + /* Release the mutex, special case for Global Lock */ + + if (obj_desc == acpi_gbl_global_lock_mutex) { + + /* Ignore errors */ + + (void)acpi_ev_release_global_lock(); + } else { + acpi_os_release_mutex(obj_desc->mutex.os_mutex); + } + + /* Mark mutex unowned */ + + obj_desc->mutex.owner_thread = NULL; + obj_desc->mutex.thread_id = NULL; + + /* Update Thread sync_level (Last mutex is the important one) */ + + thread->current_sync_level = + obj_desc->mutex.original_sync_level; + } +} diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c new file mode 100644 index 000000000000..12d3513531e1 --- /dev/null +++ b/drivers/acpi/acpica/exnames.c @@ -0,0 +1,436 @@ + +/****************************************************************************** + * + * Module Name: exnames - interpreter/scanner name load/execute + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exnames") + +/* Local prototypes */ +static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs); + +static acpi_status +acpi_ex_name_segment(u8 ** in_aml_address, char *name_string); + +/******************************************************************************* + * + * FUNCTION: acpi_ex_allocate_name_string + * + * PARAMETERS: prefix_count - Count of parent levels. Special cases: + * (-1)==root, 0==none + * num_name_segs - count of 4-character name segments + * + * RETURN: A pointer to the allocated string segment. This segment must + * be deleted by the caller. + * + * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name + * string is long enough, and set up prefix if any. + * + ******************************************************************************/ + +static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs) +{ + char *temp_ptr; + char *name_string; + u32 size_needed; + + ACPI_FUNCTION_TRACE(ex_allocate_name_string); + + /* + * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix. + * Also, one byte for the null terminator. + * This may actually be somewhat longer than needed. + */ + if (prefix_count == ACPI_UINT32_MAX) { + + /* Special case for root */ + + size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; + } else { + size_needed = + prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; + } + + /* + * Allocate a buffer for the name. + * This buffer must be deleted by the caller! + */ + name_string = ACPI_ALLOCATE(size_needed); + if (!name_string) { + ACPI_ERROR((AE_INFO, + "Could not allocate size %d", size_needed)); + return_PTR(NULL); + } + + temp_ptr = name_string; + + /* Set up Root or Parent prefixes if needed */ + + if (prefix_count == ACPI_UINT32_MAX) { + *temp_ptr++ = AML_ROOT_PREFIX; + } else { + while (prefix_count--) { + *temp_ptr++ = AML_PARENT_PREFIX; + } + } + + /* Set up Dual or Multi prefixes if needed */ + + if (num_name_segs > 2) { + + /* Set up multi prefixes */ + + *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; + *temp_ptr++ = (char)num_name_segs; + } else if (2 == num_name_segs) { + + /* Set up dual prefixes */ + + *temp_ptr++ = AML_DUAL_NAME_PREFIX; + } + + /* + * Terminate string following prefixes. acpi_ex_name_segment() will + * append the segment(s) + */ + *temp_ptr = 0; + + return_PTR(name_string); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_name_segment + * + * PARAMETERS: in_aml_address - Pointer to the name in the AML code + * name_string - Where to return the name. The name is appended + * to any existing string to form a namepath + * + * RETURN: Status + * + * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream + * + ******************************************************************************/ + +static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) +{ + char *aml_address = (void *)*in_aml_address; + acpi_status status = AE_OK; + u32 index; + char char_buf[5]; + + ACPI_FUNCTION_TRACE(ex_name_segment); + + /* + * If first character is a digit, then we know that we aren't looking at a + * valid name segment + */ + char_buf[0] = *aml_address; + + if ('0' <= char_buf[0] && char_buf[0] <= '9') { + ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0])); + return_ACPI_STATUS(AE_CTRL_PENDING); + } + + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n")); + + for (index = 0; (index < ACPI_NAME_SIZE) + && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) { + char_buf[index] = *aml_address++; + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index])); + } + + /* Valid name segment */ + + if (index == 4) { + + /* Found 4 valid characters */ + + char_buf[4] = '\0'; + + if (name_string) { + ACPI_STRCAT(name_string, char_buf); + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Appended to - %s\n", name_string)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "No Name string - %s\n", char_buf)); + } + } else if (index == 0) { + /* + * First character was not a valid name character, + * so we are looking at something other than a name. + */ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Leading character is not alpha: %02Xh (not a name)\n", + char_buf[0])); + status = AE_CTRL_PENDING; + } else { + /* + * Segment started with one or more valid characters, but fewer than + * the required 4 + */ + status = AE_AML_BAD_NAME; + ACPI_ERROR((AE_INFO, + "Bad character %02x in name, at %p", + *aml_address, aml_address)); + } + + *in_aml_address = ACPI_CAST_PTR(u8, aml_address); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_get_name_string + * + * PARAMETERS: data_type - Object type to be associated with this + * name + * in_aml_address - Pointer to the namestring in the AML code + * out_name_string - Where the namestring is returned + * out_name_length - Length of the returned string + * + * RETURN: Status, namestring and length + * + * DESCRIPTION: Extract a full namepath from the AML byte stream, + * including any prefixes. + * + ******************************************************************************/ + +acpi_status +acpi_ex_get_name_string(acpi_object_type data_type, + u8 * in_aml_address, + char **out_name_string, u32 * out_name_length) +{ + acpi_status status = AE_OK; + u8 *aml_address = in_aml_address; + char *name_string = NULL; + u32 num_segments; + u32 prefix_count = 0; + u8 has_prefix = FALSE; + + ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address); + + if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type || + ACPI_TYPE_LOCAL_BANK_FIELD == data_type || + ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) { + + /* Disallow prefixes for types associated with field_unit names */ + + name_string = acpi_ex_allocate_name_string(0, 1); + if (!name_string) { + status = AE_NO_MEMORY; + } else { + status = + acpi_ex_name_segment(&aml_address, name_string); + } + } else { + /* + * data_type is not a field name. + * Examine first character of name for root or parent prefix operators + */ + switch (*aml_address) { + case AML_ROOT_PREFIX: + + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, + "RootPrefix(\\) at %p\n", + aml_address)); + + /* + * Remember that we have a root_prefix -- + * see comment in acpi_ex_allocate_name_string() + */ + aml_address++; + prefix_count = ACPI_UINT32_MAX; + has_prefix = TRUE; + break; + + case AML_PARENT_PREFIX: + + /* Increment past possibly multiple parent prefixes */ + + do { + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, + "ParentPrefix (^) at %p\n", + aml_address)); + + aml_address++; + prefix_count++; + + } while (*aml_address == AML_PARENT_PREFIX); + + has_prefix = TRUE; + break; + + default: + + /* Not a prefix character */ + + break; + } + + /* Examine first character of name for name segment prefix operator */ + + switch (*aml_address) { + case AML_DUAL_NAME_PREFIX: + + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, + "DualNamePrefix at %p\n", + aml_address)); + + aml_address++; + name_string = + acpi_ex_allocate_name_string(prefix_count, 2); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + /* Indicate that we processed a prefix */ + + has_prefix = TRUE; + + status = + acpi_ex_name_segment(&aml_address, name_string); + if (ACPI_SUCCESS(status)) { + status = + acpi_ex_name_segment(&aml_address, + name_string); + } + break; + + case AML_MULTI_NAME_PREFIX_OP: + + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, + "MultiNamePrefix at %p\n", + aml_address)); + + /* Fetch count of segments remaining in name path */ + + aml_address++; + num_segments = *aml_address; + + name_string = + acpi_ex_allocate_name_string(prefix_count, + num_segments); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + /* Indicate that we processed a prefix */ + + aml_address++; + has_prefix = TRUE; + + while (num_segments && + (status = + acpi_ex_name_segment(&aml_address, + name_string)) == AE_OK) { + num_segments--; + } + + break; + + case 0: + + /* null_name valid as of 8-12-98 ASL/AML Grammar Update */ + + if (prefix_count == ACPI_UINT32_MAX) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "NameSeg is \"\\\" followed by NULL\n")); + } + + /* Consume the NULL byte */ + + aml_address++; + name_string = + acpi_ex_allocate_name_string(prefix_count, 0); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + break; + + default: + + /* Name segment string */ + + name_string = + acpi_ex_allocate_name_string(prefix_count, 1); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + status = + acpi_ex_name_segment(&aml_address, name_string); + break; + } + } + + if (AE_CTRL_PENDING == status && has_prefix) { + + /* Ran out of segments after processing a prefix */ + + ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string)); + status = AE_AML_BAD_NAME; + } + + if (ACPI_FAILURE(status)) { + if (name_string) { + ACPI_FREE(name_string); + } + return_ACPI_STATUS(status); + } + + *out_name_string = name_string; + *out_name_length = (u32) (aml_address - in_aml_address); + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c new file mode 100644 index 000000000000..52d78b8622be --- /dev/null +++ b/drivers/acpi/acpica/exoparg1.c @@ -0,0 +1,1050 @@ + +/****************************************************************************** + * + * Module Name: exoparg1 - AML execution - opcodes with 1 argument + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exoparg1") + +/*! + * Naming convention for AML interpreter execution routines. + * + * The routines that begin execution of AML opcodes are named with a common + * convention based upon the number of arguments, the number of target operands, + * and whether or not a value is returned: + * + * AcpiExOpcode_xA_yT_zR + * + * Where: + * + * xA - ARGUMENTS: The number of arguments (input operands) that are + * required for this opcode type (0 through 6 args). + * yT - TARGETS: The number of targets (output operands) that are required + * for this opcode type (0, 1, or 2 targets). + * zR - RETURN VALUE: Indicates whether this opcode type returns a value + * as the function return (0 or 1). + * + * The AcpiExOpcode* functions are called via the Dispatcher component with + * fully resolved operands. +!*/ +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_0A_0T_1R + * + * PARAMETERS: walk_state - Current state (contains AML opcode) + * + * RETURN: Status + * + * DESCRIPTION: Execute operator with no operands, one return value + * + ******************************************************************************/ +acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_operand_object *return_desc = NULL; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_0A_0T_1R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + /* Examine the AML opcode */ + + switch (walk_state->opcode) { + case AML_TIMER_OP: /* Timer () */ + + /* Create a return object of type Integer */ + + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + return_desc->integer.value = acpi_os_get_timer(); + break; + + default: /* Unknown opcode */ + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + break; + } + + cleanup: + + /* Delete return object on error */ + + if ((ACPI_FAILURE(status)) || walk_state->result_obj) { + acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; + } else { + /* Save the return value */ + + walk_state->result_obj = return_desc; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_1A_0T_0R + * + * PARAMETERS: walk_state - Current state (contains AML opcode) + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on + * object stack + * + ******************************************************************************/ + +acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_0R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + /* Examine the AML opcode */ + + switch (walk_state->opcode) { + case AML_RELEASE_OP: /* Release (mutex_object) */ + + status = acpi_ex_release_mutex(operand[0], walk_state); + break; + + case AML_RESET_OP: /* Reset (event_object) */ + + status = acpi_ex_system_reset_event(operand[0]); + break; + + case AML_SIGNAL_OP: /* Signal (event_object) */ + + status = acpi_ex_system_signal_event(operand[0]); + break; + + case AML_SLEEP_OP: /* Sleep (msec_time) */ + + status = acpi_ex_system_do_suspend(operand[0]->integer.value); + break; + + case AML_STALL_OP: /* Stall (usec_time) */ + + status = + acpi_ex_system_do_stall((u32) operand[0]->integer.value); + break; + + case AML_UNLOAD_OP: /* Unload (Handle) */ + + status = acpi_ex_unload_table(operand[0]); + break; + + default: /* Unknown opcode */ + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + break; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_1A_1T_0R + * + * PARAMETERS: walk_state - Current state (contains AML opcode) + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with one argument, one target, and no + * return value. + * + ******************************************************************************/ + +acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_operand_object **operand = &walk_state->operands[0]; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_0R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + /* Examine the AML opcode */ + + switch (walk_state->opcode) { + case AML_LOAD_OP: + + status = acpi_ex_load_op(operand[0], operand[1], walk_state); + break; + + default: /* Unknown opcode */ + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + cleanup: + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_1A_1T_1R + * + * PARAMETERS: walk_state - Current state (contains AML opcode) + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with one argument, one target, and a + * return value. + * + ******************************************************************************/ + +acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *return_desc = NULL; + union acpi_operand_object *return_desc2 = NULL; + u32 temp32; + u32 i; + acpi_integer power_of_ten; + acpi_integer digit; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_1R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + /* Examine the AML opcode */ + + switch (walk_state->opcode) { + case AML_BIT_NOT_OP: + case AML_FIND_SET_LEFT_BIT_OP: + case AML_FIND_SET_RIGHT_BIT_OP: + case AML_FROM_BCD_OP: + case AML_TO_BCD_OP: + case AML_COND_REF_OF_OP: + + /* Create a return object of type Integer for these opcodes */ + + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + switch (walk_state->opcode) { + case AML_BIT_NOT_OP: /* Not (Operand, Result) */ + + return_desc->integer.value = ~operand[0]->integer.value; + break; + + case AML_FIND_SET_LEFT_BIT_OP: /* find_set_left_bit (Operand, Result) */ + + return_desc->integer.value = operand[0]->integer.value; + + /* + * Acpi specification describes Integer type as a little + * endian unsigned value, so this boundary condition is valid. + */ + for (temp32 = 0; return_desc->integer.value && + temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { + return_desc->integer.value >>= 1; + } + + return_desc->integer.value = temp32; + break; + + case AML_FIND_SET_RIGHT_BIT_OP: /* find_set_right_bit (Operand, Result) */ + + return_desc->integer.value = operand[0]->integer.value; + + /* + * The Acpi specification describes Integer type as a little + * endian unsigned value, so this boundary condition is valid. + */ + for (temp32 = 0; return_desc->integer.value && + temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { + return_desc->integer.value <<= 1; + } + + /* Since the bit position is one-based, subtract from 33 (65) */ + + return_desc->integer.value = + temp32 == + 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32; + break; + + case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */ + + /* + * The 64-bit ACPI integer can hold 16 4-bit BCD characters + * (if table is 32-bit, integer can hold 8 BCD characters) + * Convert each 4-bit BCD value + */ + power_of_ten = 1; + return_desc->integer.value = 0; + digit = operand[0]->integer.value; + + /* Convert each BCD digit (each is one nybble wide) */ + + for (i = 0; + (i < acpi_gbl_integer_nybble_width) && (digit > 0); + i++) { + + /* Get the least significant 4-bit BCD digit */ + + temp32 = ((u32) digit) & 0xF; + + /* Check the range of the digit */ + + if (temp32 > 9) { + ACPI_ERROR((AE_INFO, + "BCD digit too large (not decimal): 0x%X", + temp32)); + + status = AE_AML_NUMERIC_OVERFLOW; + goto cleanup; + } + + /* Sum the digit into the result with the current power of 10 */ + + return_desc->integer.value += + (((acpi_integer) temp32) * power_of_ten); + + /* Shift to next BCD digit */ + + digit >>= 4; + + /* Next power of 10 */ + + power_of_ten *= 10; + } + break; + + case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */ + + return_desc->integer.value = 0; + digit = operand[0]->integer.value; + + /* Each BCD digit is one nybble wide */ + + for (i = 0; + (i < acpi_gbl_integer_nybble_width) && (digit > 0); + i++) { + (void)acpi_ut_short_divide(digit, 10, &digit, + &temp32); + + /* + * Insert the BCD digit that resides in the + * remainder from above + */ + return_desc->integer.value |= + (((acpi_integer) temp32) << ACPI_MUL_4(i)); + } + + /* Overflow if there is any data left in Digit */ + + if (digit > 0) { + ACPI_ERROR((AE_INFO, + "Integer too large to convert to BCD: %8.8X%8.8X", + ACPI_FORMAT_UINT64(operand[0]-> + integer.value))); + status = AE_AML_NUMERIC_OVERFLOW; + goto cleanup; + } + break; + + case AML_COND_REF_OF_OP: /* cond_ref_of (source_object, Result) */ + + /* + * This op is a little strange because the internal return value is + * different than the return value stored in the result descriptor + * (There are really two return values) + */ + if ((struct acpi_namespace_node *)operand[0] == + acpi_gbl_root_node) { + /* + * This means that the object does not exist in the namespace, + * return FALSE + */ + return_desc->integer.value = 0; + goto cleanup; + } + + /* Get the object reference, store it, and remove our reference */ + + status = acpi_ex_get_object_reference(operand[0], + &return_desc2, + walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + status = + acpi_ex_store(return_desc2, operand[1], walk_state); + acpi_ut_remove_reference(return_desc2); + + /* The object exists in the namespace, return TRUE */ + + return_desc->integer.value = ACPI_INTEGER_MAX; + goto cleanup; + + default: + /* No other opcodes get here */ + break; + } + break; + + case AML_STORE_OP: /* Store (Source, Target) */ + + /* + * A store operand is typically a number, string, buffer or lvalue + * Be careful about deleting the source object, + * since the object itself may have been stored. + */ + status = acpi_ex_store(operand[0], operand[1], walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* It is possible that the Store already produced a return object */ + + if (!walk_state->result_obj) { + /* + * Normally, we would remove a reference on the Operand[0] + * parameter; But since it is being used as the internal return + * object (meaning we would normally increment it), the two + * cancel out, and we simply don't do anything. + */ + walk_state->result_obj = operand[0]; + walk_state->operands[0] = NULL; /* Prevent deletion */ + } + return_ACPI_STATUS(status); + + /* + * ACPI 2.0 Opcodes + */ + case AML_COPY_OP: /* Copy (Source, Target) */ + + status = + acpi_ut_copy_iobject_to_iobject(operand[0], &return_desc, + walk_state); + break; + + case AML_TO_DECSTRING_OP: /* to_decimal_string (Data, Result) */ + + status = acpi_ex_convert_to_string(operand[0], &return_desc, + ACPI_EXPLICIT_CONVERT_DECIMAL); + if (return_desc == operand[0]) { + + /* No conversion performed, add ref to handle return value */ + acpi_ut_add_reference(return_desc); + } + break; + + case AML_TO_HEXSTRING_OP: /* to_hex_string (Data, Result) */ + + status = acpi_ex_convert_to_string(operand[0], &return_desc, + ACPI_EXPLICIT_CONVERT_HEX); + if (return_desc == operand[0]) { + + /* No conversion performed, add ref to handle return value */ + acpi_ut_add_reference(return_desc); + } + break; + + case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */ + + status = acpi_ex_convert_to_buffer(operand[0], &return_desc); + if (return_desc == operand[0]) { + + /* No conversion performed, add ref to handle return value */ + acpi_ut_add_reference(return_desc); + } + break; + + case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */ + + status = acpi_ex_convert_to_integer(operand[0], &return_desc, + ACPI_ANY_BASE); + if (return_desc == operand[0]) { + + /* No conversion performed, add ref to handle return value */ + acpi_ut_add_reference(return_desc); + } + break; + + case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */ + case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */ + + /* These are two obsolete opcodes */ + + ACPI_ERROR((AE_INFO, + "%s is obsolete and not implemented", + acpi_ps_get_opcode_name(walk_state->opcode))); + status = AE_SUPPORT; + goto cleanup; + + default: /* Unknown opcode */ + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + if (ACPI_SUCCESS(status)) { + + /* Store the return value computed above into the target object */ + + status = acpi_ex_store(return_desc, operand[1], walk_state); + } + + cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(return_desc); + } + + /* Save return object on success */ + + else if (!walk_state->result_obj) { + walk_state->result_obj = return_desc; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_1A_0T_1R + * + * PARAMETERS: walk_state - Current state (contains AML opcode) + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with one argument, no target, and a return value + * + ******************************************************************************/ + +acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *temp_desc; + union acpi_operand_object *return_desc = NULL; + acpi_status status = AE_OK; + u32 type; + acpi_integer value; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_1R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + /* Examine the AML opcode */ + + switch (walk_state->opcode) { + case AML_LNOT_OP: /* LNot (Operand) */ + + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Set result to ONES (TRUE) if Value == 0. Note: + * return_desc->Integer.Value is initially == 0 (FALSE) from above. + */ + if (!operand[0]->integer.value) { + return_desc->integer.value = ACPI_INTEGER_MAX; + } + break; + + case AML_DECREMENT_OP: /* Decrement (Operand) */ + case AML_INCREMENT_OP: /* Increment (Operand) */ + + /* + * Create a new integer. Can't just get the base integer and + * increment it because it may be an Arg or Field. + */ + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Since we are expecting a Reference operand, it can be either a + * NS Node or an internal object. + */ + temp_desc = operand[0]; + if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) == + ACPI_DESC_TYPE_OPERAND) { + + /* Internal reference object - prevent deletion */ + + acpi_ut_add_reference(temp_desc); + } + + /* + * Convert the Reference operand to an Integer (This removes a + * reference on the Operand[0] object) + * + * NOTE: We use LNOT_OP here in order to force resolution of the + * reference operand to an actual integer. + */ + status = + acpi_ex_resolve_operands(AML_LNOT_OP, &temp_desc, + walk_state); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "While resolving operands for [%s]", + acpi_ps_get_opcode_name(walk_state-> + opcode))); + + goto cleanup; + } + + /* + * temp_desc is now guaranteed to be an Integer object -- + * Perform the actual increment or decrement + */ + if (walk_state->opcode == AML_INCREMENT_OP) { + return_desc->integer.value = + temp_desc->integer.value + 1; + } else { + return_desc->integer.value = + temp_desc->integer.value - 1; + } + + /* Finished with this Integer object */ + + acpi_ut_remove_reference(temp_desc); + + /* + * Store the result back (indirectly) through the original + * Reference object + */ + status = acpi_ex_store(return_desc, operand[0], walk_state); + break; + + case AML_TYPE_OP: /* object_type (source_object) */ + + /* + * Note: The operand is not resolved at this point because we want to + * get the associated object, not its value. For example, we don't + * want to resolve a field_unit to its value, we want the actual + * field_unit object. + */ + + /* Get the type of the base object */ + + status = + acpi_ex_resolve_multiple(walk_state, operand[0], &type, + NULL); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Allocate a descriptor to hold the type. */ + + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + return_desc->integer.value = type; + break; + + case AML_SIZE_OF_OP: /* size_of (source_object) */ + + /* + * Note: The operand is not resolved at this point because we want to + * get the associated object, not its value. + */ + + /* Get the base object */ + + status = acpi_ex_resolve_multiple(walk_state, + operand[0], &type, + &temp_desc); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* + * The type of the base object must be integer, buffer, string, or + * package. All others are not supported. + * + * NOTE: Integer is not specifically supported by the ACPI spec, + * but is supported implicitly via implicit operand conversion. + * rather than bother with conversion, we just use the byte width + * global (4 or 8 bytes). + */ + switch (type) { + case ACPI_TYPE_INTEGER: + value = acpi_gbl_integer_byte_width; + break; + + case ACPI_TYPE_STRING: + value = temp_desc->string.length; + break; + + case ACPI_TYPE_BUFFER: + + /* Buffer arguments may not be evaluated at this point */ + + status = acpi_ds_get_buffer_arguments(temp_desc); + value = temp_desc->buffer.length; + break; + + case ACPI_TYPE_PACKAGE: + + /* Package arguments may not be evaluated at this point */ + + status = acpi_ds_get_package_arguments(temp_desc); + value = temp_desc->package.count; + break; + + default: + ACPI_ERROR((AE_INFO, + "Operand must be Buffer/Integer/String/Package - found type %s", + acpi_ut_get_type_name(type))); + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* + * Now that we have the size of the object, create a result + * object to hold the value + */ + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + return_desc->integer.value = value; + break; + + case AML_REF_OF_OP: /* ref_of (source_object) */ + + status = + acpi_ex_get_object_reference(operand[0], &return_desc, + walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + break; + + case AML_DEREF_OF_OP: /* deref_of (obj_reference | String) */ + + /* Check for a method local or argument, or standalone String */ + + if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) == + ACPI_DESC_TYPE_NAMED) { + temp_desc = + acpi_ns_get_attached_object((struct + acpi_namespace_node *) + operand[0]); + if (temp_desc + && + ((ACPI_GET_OBJECT_TYPE(temp_desc) == + ACPI_TYPE_STRING) + || (ACPI_GET_OBJECT_TYPE(temp_desc) == + ACPI_TYPE_LOCAL_REFERENCE))) { + operand[0] = temp_desc; + acpi_ut_add_reference(temp_desc); + } else { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + } else { + switch (ACPI_GET_OBJECT_TYPE(operand[0])) { + case ACPI_TYPE_LOCAL_REFERENCE: + /* + * This is a deref_of (local_x | arg_x) + * + * Must resolve/dereference the local/arg reference first + */ + switch (operand[0]->reference.class) { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + + /* Set Operand[0] to the value of the local/arg */ + + status = + acpi_ds_method_data_get_value + (operand[0]->reference.class, + operand[0]->reference.value, + walk_state, &temp_desc); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* + * Delete our reference to the input object and + * point to the object just retrieved + */ + acpi_ut_remove_reference(operand[0]); + operand[0] = temp_desc; + break; + + case ACPI_REFCLASS_REFOF: + + /* Get the object to which the reference refers */ + + temp_desc = + operand[0]->reference.object; + acpi_ut_remove_reference(operand[0]); + operand[0] = temp_desc; + break; + + default: + + /* Must be an Index op - handled below */ + break; + } + break; + + case ACPI_TYPE_STRING: + break; + + default: + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + } + + if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) != + ACPI_DESC_TYPE_NAMED) { + if (ACPI_GET_OBJECT_TYPE(operand[0]) == + ACPI_TYPE_STRING) { + /* + * This is a deref_of (String). The string is a reference + * to a named ACPI object. + * + * 1) Find the owning Node + * 2) Dereference the node to an actual object. Could be a + * Field, so we need to resolve the node to a value. + */ + status = + acpi_ns_get_node(walk_state->scope_info-> + scope.node, + operand[0]->string.pointer, + ACPI_NS_SEARCH_PARENT, + ACPI_CAST_INDIRECT_PTR + (struct + acpi_namespace_node, + &return_desc)); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + status = + acpi_ex_resolve_node_to_value + (ACPI_CAST_INDIRECT_PTR + (struct acpi_namespace_node, &return_desc), + walk_state); + goto cleanup; + } + } + + /* Operand[0] may have changed from the code above */ + + if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) == + ACPI_DESC_TYPE_NAMED) { + /* + * This is a deref_of (object_reference) + * Get the actual object from the Node (This is the dereference). + * This case may only happen when a local_x or arg_x is + * dereferenced above. + */ + return_desc = acpi_ns_get_attached_object((struct + acpi_namespace_node + *) + operand[0]); + acpi_ut_add_reference(return_desc); + } else { + /* + * This must be a reference object produced by either the + * Index() or ref_of() operator + */ + switch (operand[0]->reference.class) { + case ACPI_REFCLASS_INDEX: + + /* + * The target type for the Index operator must be + * either a Buffer or a Package + */ + switch (operand[0]->reference.target_type) { + case ACPI_TYPE_BUFFER_FIELD: + + temp_desc = + operand[0]->reference.object; + + /* + * Create a new object that contains one element of the + * buffer -- the element pointed to by the index. + * + * NOTE: index into a buffer is NOT a pointer to a + * sub-buffer of the main buffer, it is only a pointer to a + * single element (byte) of the buffer! + */ + return_desc = + acpi_ut_create_internal_object + (ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Since we are returning the value of the buffer at the + * indexed location, we don't need to add an additional + * reference to the buffer itself. + */ + return_desc->integer.value = + temp_desc->buffer. + pointer[operand[0]->reference. + value]; + break; + + case ACPI_TYPE_PACKAGE: + + /* + * Return the referenced element of the package. We must + * add another reference to the referenced object, however. + */ + return_desc = + *(operand[0]->reference.where); + if (return_desc) { + acpi_ut_add_reference + (return_desc); + } + break; + + default: + + ACPI_ERROR((AE_INFO, + "Unknown Index TargetType %X in reference object %p", + operand[0]->reference. + target_type, operand[0])); + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + break; + + case ACPI_REFCLASS_REFOF: + + return_desc = operand[0]->reference.object; + + if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) == + ACPI_DESC_TYPE_NAMED) { + return_desc = + acpi_ns_get_attached_object((struct + acpi_namespace_node + *) + return_desc); + } + + /* Add another reference to the object! */ + + acpi_ut_add_reference(return_desc); + break; + + default: + ACPI_ERROR((AE_INFO, + "Unknown class in reference(%p) - %2.2X", + operand[0], + operand[0]->reference.class)); + + status = AE_TYPE; + goto cleanup; + } + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(return_desc); + } + + /* Save return object on success */ + + else { + walk_state->result_obj = return_desc; + } + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c new file mode 100644 index 000000000000..b01980df1365 --- /dev/null +++ b/drivers/acpi/acpica/exoparg2.c @@ -0,0 +1,605 @@ +/****************************************************************************** + * + * Module Name: exoparg2 - AML execution - opcodes with 2 arguments + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exoparg2") + +/*! + * Naming convention for AML interpreter execution routines. + * + * The routines that begin execution of AML opcodes are named with a common + * convention based upon the number of arguments, the number of target operands, + * and whether or not a value is returned: + * + * AcpiExOpcode_xA_yT_zR + * + * Where: + * + * xA - ARGUMENTS: The number of arguments (input operands) that are + * required for this opcode type (1 through 6 args). + * yT - TARGETS: The number of targets (output operands) that are required + * for this opcode type (0, 1, or 2 targets). + * zR - RETURN VALUE: Indicates whether this opcode type returns a value + * as the function return (0 or 1). + * + * The AcpiExOpcode* functions are called via the Dispatcher component with + * fully resolved operands. +!*/ +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_2A_0T_0R + * + * PARAMETERS: walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with two arguments, no target, and no return + * value. + * + * ALLOCATION: Deletes both operands + * + ******************************************************************************/ +acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + struct acpi_namespace_node *node; + u32 value; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + /* Examine the opcode */ + + switch (walk_state->opcode) { + case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */ + + /* The first operand is a namespace node */ + + node = (struct acpi_namespace_node *)operand[0]; + + /* Second value is the notify value */ + + value = (u32) operand[1]->integer.value; + + /* Are notifies allowed on this object? */ + + if (!acpi_ev_is_notify_object(node)) { + ACPI_ERROR((AE_INFO, + "Unexpected notify object type [%s]", + acpi_ut_get_type_name(node->type))); + + status = AE_AML_OPERAND_TYPE; + break; + } +#ifdef ACPI_GPE_NOTIFY_CHECK + /* + * GPE method wake/notify check. Here, we want to ensure that we + * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx + * GPE method during system runtime. If we do, the GPE is marked + * as "wake-only" and disabled. + * + * 1) Is the Notify() value == device_wake? + * 2) Is this a GPE deferred method? (An _Lxx or _Exx method) + * 3) Did the original GPE happen at system runtime? + * (versus during wake) + * + * If all three cases are true, this is a wake-only GPE that should + * be disabled at runtime. + */ + if (value == 2) { /* device_wake */ + status = + acpi_ev_check_for_wake_only_gpe(walk_state-> + gpe_event_info); + if (ACPI_FAILURE(status)) { + + /* AE_WAKE_ONLY_GPE only error, means ignore this notify */ + + return_ACPI_STATUS(AE_OK) + } + } +#endif + + /* + * Dispatch the notify to the appropriate handler + * NOTE: the request is queued for execution after this method + * completes. The notify handlers are NOT invoked synchronously + * from this thread -- because handlers may in turn run other + * control methods. + */ + status = acpi_ev_queue_notify_request(node, value); + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_2A_2T_1R + * + * PARAMETERS: walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets + * and one implicit return value. + * + ******************************************************************************/ + +acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *return_desc1 = NULL; + union acpi_operand_object *return_desc2 = NULL; + acpi_status status; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + /* Execute the opcode */ + + switch (walk_state->opcode) { + case AML_DIVIDE_OP: + + /* Divide (Dividend, Divisor, remainder_result quotient_result) */ + + return_desc1 = + acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc1) { + status = AE_NO_MEMORY; + goto cleanup; + } + + return_desc2 = + acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc2) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Quotient to return_desc1, remainder to return_desc2 */ + + status = acpi_ut_divide(operand[0]->integer.value, + operand[1]->integer.value, + &return_desc1->integer.value, + &return_desc2->integer.value); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + /* Store the results to the target reference operands */ + + status = acpi_ex_store(return_desc2, operand[2], walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + status = acpi_ex_store(return_desc1, operand[3], walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + cleanup: + /* + * Since the remainder is not returned indirectly, remove a reference to + * it. Only the quotient is returned indirectly. + */ + acpi_ut_remove_reference(return_desc2); + + if (ACPI_FAILURE(status)) { + + /* Delete the return object */ + + acpi_ut_remove_reference(return_desc1); + } + + /* Save return object (the remainder) on success */ + + else { + walk_state->result_obj = return_desc1; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_2A_1T_1R + * + * PARAMETERS: walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with two arguments, one target, and a return + * value. + * + ******************************************************************************/ + +acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *return_desc = NULL; + acpi_integer index; + acpi_status status = AE_OK; + acpi_size length; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + /* Execute the opcode */ + + if (walk_state->op_info->flags & AML_MATH) { + + /* All simple math opcodes (add, etc.) */ + + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + return_desc->integer.value = + acpi_ex_do_math_op(walk_state->opcode, + operand[0]->integer.value, + operand[1]->integer.value); + goto store_result_to_target; + } + + switch (walk_state->opcode) { + case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */ + + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* return_desc will contain the remainder */ + + status = acpi_ut_divide(operand[0]->integer.value, + operand[1]->integer.value, + NULL, &return_desc->integer.value); + break; + + case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */ + + status = acpi_ex_do_concatenate(operand[0], operand[1], + &return_desc, walk_state); + break; + + case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */ + + /* + * Input object is guaranteed to be a buffer at this point (it may have + * been converted.) Copy the raw buffer data to a new object of + * type String. + */ + + /* + * Get the length of the new string. It is the smallest of: + * 1) Length of the input buffer + * 2) Max length as specified in the to_string operator + * 3) Length of input buffer up to a zero byte (null terminator) + * + * NOTE: A length of zero is ok, and will create a zero-length, null + * terminated string. + */ + length = 0; + while ((length < operand[0]->buffer.length) && + (length < operand[1]->integer.value) && + (operand[0]->buffer.pointer[length])) { + length++; + } + + /* Allocate a new string object */ + + return_desc = acpi_ut_create_string_object(length); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Copy the raw buffer data with no transform. + * (NULL terminated already) + */ + ACPI_MEMCPY(return_desc->string.pointer, + operand[0]->buffer.pointer, length); + break; + + case AML_CONCAT_RES_OP: + + /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */ + + status = acpi_ex_concat_template(operand[0], operand[1], + &return_desc, walk_state); + break; + + case AML_INDEX_OP: /* Index (Source Index Result) */ + + /* Create the internal return object */ + + return_desc = + acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Initialize the Index reference object */ + + index = operand[1]->integer.value; + return_desc->reference.value = (u32) index; + return_desc->reference.class = ACPI_REFCLASS_INDEX; + + /* + * At this point, the Source operand is a String, Buffer, or Package. + * Verify that the index is within range. + */ + switch (ACPI_GET_OBJECT_TYPE(operand[0])) { + case ACPI_TYPE_STRING: + + if (index >= operand[0]->string.length) { + status = AE_AML_STRING_LIMIT; + } + + return_desc->reference.target_type = + ACPI_TYPE_BUFFER_FIELD; + break; + + case ACPI_TYPE_BUFFER: + + if (index >= operand[0]->buffer.length) { + status = AE_AML_BUFFER_LIMIT; + } + + return_desc->reference.target_type = + ACPI_TYPE_BUFFER_FIELD; + break; + + case ACPI_TYPE_PACKAGE: + + if (index >= operand[0]->package.count) { + status = AE_AML_PACKAGE_LIMIT; + } + + return_desc->reference.target_type = ACPI_TYPE_PACKAGE; + return_desc->reference.where = + &operand[0]->package.elements[index]; + break; + + default: + + status = AE_AML_INTERNAL; + goto cleanup; + } + + /* Failure means that the Index was beyond the end of the object */ + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Index (%X%8.8X) is beyond end of object", + ACPI_FORMAT_UINT64(index))); + goto cleanup; + } + + /* + * Save the target object and add a reference to it for the life + * of the index + */ + return_desc->reference.object = operand[0]; + acpi_ut_add_reference(operand[0]); + + /* Store the reference to the Target */ + + status = acpi_ex_store(return_desc, operand[2], walk_state); + + /* Return the reference */ + + walk_state->result_obj = return_desc; + goto cleanup; + + default: + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + break; + } + + store_result_to_target: + + if (ACPI_SUCCESS(status)) { + /* + * Store the result of the operation (which is now in return_desc) into + * the Target descriptor. + */ + status = acpi_ex_store(return_desc, operand[2], walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + if (!walk_state->result_obj) { + walk_state->result_obj = return_desc; + } + } + + cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_2A_0T_1R + * + * PARAMETERS: walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value + * + ******************************************************************************/ + +acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *return_desc = NULL; + acpi_status status = AE_OK; + u8 logical_result = FALSE; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + /* Create the internal return object */ + + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Execute the Opcode */ + + if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) { + + /* logical_op (Operand0, Operand1) */ + + status = acpi_ex_do_logical_numeric_op(walk_state->opcode, + operand[0]->integer. + value, + operand[1]->integer. + value, &logical_result); + goto store_logical_result; + } else if (walk_state->op_info->flags & AML_LOGICAL) { + + /* logical_op (Operand0, Operand1) */ + + status = acpi_ex_do_logical_op(walk_state->opcode, operand[0], + operand[1], &logical_result); + goto store_logical_result; + } + + switch (walk_state->opcode) { + case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */ + + status = + acpi_ex_acquire_mutex(operand[1], operand[0], walk_state); + if (status == AE_TIME) { + logical_result = TRUE; /* TRUE = Acquire timed out */ + status = AE_OK; + } + break; + + case AML_WAIT_OP: /* Wait (event_object, Timeout) */ + + status = acpi_ex_system_wait_event(operand[1], operand[0]); + if (status == AE_TIME) { + logical_result = TRUE; /* TRUE, Wait timed out */ + status = AE_OK; + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + store_logical_result: + /* + * Set return value to according to logical_result. logical TRUE (all ones) + * Default is FALSE (zero) + */ + if (logical_result) { + return_desc->integer.value = ACPI_INTEGER_MAX; + } + + cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(return_desc); + } + + /* Save return object on success */ + + else { + walk_state->result_obj = return_desc; + } + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c new file mode 100644 index 000000000000..26dbd5c2c1da --- /dev/null +++ b/drivers/acpi/acpica/exoparg3.c @@ -0,0 +1,273 @@ + +/****************************************************************************** + * + * Module Name: exoparg3 - AML execution - opcodes with 3 arguments + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exoparg3") + +/*! + * Naming convention for AML interpreter execution routines. + * + * The routines that begin execution of AML opcodes are named with a common + * convention based upon the number of arguments, the number of target operands, + * and whether or not a value is returned: + * + * AcpiExOpcode_xA_yT_zR + * + * Where: + * + * xA - ARGUMENTS: The number of arguments (input operands) that are + * required for this opcode type (1 through 6 args). + * yT - TARGETS: The number of targets (output operands) that are required + * for this opcode type (0, 1, or 2 targets). + * zR - RETURN VALUE: Indicates whether this opcode type returns a value + * as the function return (0 or 1). + * + * The AcpiExOpcode* functions are called via the Dispatcher component with + * fully resolved operands. +!*/ +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_3A_0T_0R + * + * PARAMETERS: walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute Triadic operator (3 operands) + * + ******************************************************************************/ +acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + struct acpi_signal_fatal_info *fatal; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + switch (walk_state->opcode) { + case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */ + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", + (u32) operand[0]->integer.value, + (u32) operand[1]->integer.value, + (u32) operand[2]->integer.value)); + + fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); + if (fatal) { + fatal->type = (u32) operand[0]->integer.value; + fatal->code = (u32) operand[1]->integer.value; + fatal->argument = (u32) operand[2]->integer.value; + } + + /* Always signal the OS! */ + + status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal); + + /* Might return while OS is shutting down, just continue */ + + ACPI_FREE(fatal); + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + cleanup: + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_3A_1T_1R + * + * PARAMETERS: walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute Triadic operator (3 operands) + * + ******************************************************************************/ + +acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *return_desc = NULL; + char *buffer = NULL; + acpi_status status = AE_OK; + acpi_integer index; + acpi_size length; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + switch (walk_state->opcode) { + case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */ + + /* + * Create the return object. The Source operand is guaranteed to be + * either a String or a Buffer, so just use its type. + */ + return_desc = + acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE + (operand[0])); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Get the Integer values from the objects */ + + index = operand[1]->integer.value; + length = (acpi_size) operand[2]->integer.value; + + /* + * If the index is beyond the length of the String/Buffer, or if the + * requested length is zero, return a zero-length String/Buffer + */ + if (index >= operand[0]->string.length) { + length = 0; + } + + /* Truncate request if larger than the actual String/Buffer */ + + else if ((index + length) > operand[0]->string.length) { + length = (acpi_size) operand[0]->string.length - + (acpi_size) index; + } + + /* Strings always have a sub-pointer, not so for buffers */ + + switch (ACPI_GET_OBJECT_TYPE(operand[0])) { + case ACPI_TYPE_STRING: + + /* Always allocate a new buffer for the String */ + + buffer = ACPI_ALLOCATE_ZEROED((acpi_size) length + 1); + if (!buffer) { + status = AE_NO_MEMORY; + goto cleanup; + } + break; + + case ACPI_TYPE_BUFFER: + + /* If the requested length is zero, don't allocate a buffer */ + + if (length > 0) { + + /* Allocate a new buffer for the Buffer */ + + buffer = ACPI_ALLOCATE_ZEROED(length); + if (!buffer) { + status = AE_NO_MEMORY; + goto cleanup; + } + } + break; + + default: /* Should not happen */ + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + if (buffer) { + + /* We have a buffer, copy the portion requested */ + + ACPI_MEMCPY(buffer, operand[0]->string.pointer + index, + length); + } + + /* Set the length of the new String/Buffer */ + + return_desc->string.pointer = buffer; + return_desc->string.length = (u32) length; + + /* Mark buffer initialized */ + + return_desc->buffer.flags |= AOPOBJ_DATA_VALID; + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + /* Store the result in the target */ + + status = acpi_ex_store(return_desc, operand[3], walk_state); + + cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE(status) || walk_state->result_obj) { + acpi_ut_remove_reference(return_desc); + walk_state->result_obj = NULL; + } + + /* Set the return object and exit */ + + else { + walk_state->result_obj = return_desc; + } + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c new file mode 100644 index 000000000000..bbbba504979f --- /dev/null +++ b/drivers/acpi/acpica/exoparg6.c @@ -0,0 +1,341 @@ + +/****************************************************************************** + * + * Module Name: exoparg6 - AML execution - opcodes with 6 arguments + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exoparg6") + +/*! + * Naming convention for AML interpreter execution routines. + * + * The routines that begin execution of AML opcodes are named with a common + * convention based upon the number of arguments, the number of target operands, + * and whether or not a value is returned: + * + * AcpiExOpcode_xA_yT_zR + * + * Where: + * + * xA - ARGUMENTS: The number of arguments (input operands) that are + * required for this opcode type (1 through 6 args). + * yT - TARGETS: The number of targets (output operands) that are required + * for this opcode type (0, 1, or 2 targets). + * zR - RETURN VALUE: Indicates whether this opcode type returns a value + * as the function return (0 or 1). + * + * The AcpiExOpcode* functions are called via the Dispatcher component with + * fully resolved operands. +!*/ +/* Local prototypes */ +static u8 +acpi_ex_do_match(u32 match_op, + union acpi_operand_object *package_obj, + union acpi_operand_object *match_obj); + +/******************************************************************************* + * + * FUNCTION: acpi_ex_do_match + * + * PARAMETERS: match_op - The AML match operand + * package_obj - Object from the target package + * match_obj - Object to be matched + * + * RETURN: TRUE if the match is successful, FALSE otherwise + * + * DESCRIPTION: Implements the low-level match for the ASL Match operator. + * Package elements will be implicitly converted to the type of + * the match object (Integer/Buffer/String). + * + ******************************************************************************/ + +static u8 +acpi_ex_do_match(u32 match_op, + union acpi_operand_object *package_obj, + union acpi_operand_object *match_obj) +{ + u8 logical_result = TRUE; + acpi_status status; + + /* + * Note: Since the package_obj/match_obj ordering is opposite to that of + * the standard logical operators, we have to reverse them when we call + * do_logical_op in order to make the implicit conversion rules work + * correctly. However, this means we have to flip the entire equation + * also. A bit ugly perhaps, but overall, better than fussing the + * parameters around at runtime, over and over again. + * + * Below, P[i] refers to the package element, M refers to the Match object. + */ + switch (match_op) { + case MATCH_MTR: + + /* Always true */ + + break; + + case MATCH_MEQ: + + /* + * True if equal: (P[i] == M) + * Change to: (M == P[i]) + */ + status = + acpi_ex_do_logical_op(AML_LEQUAL_OP, match_obj, package_obj, + &logical_result); + if (ACPI_FAILURE(status)) { + return (FALSE); + } + break; + + case MATCH_MLE: + + /* + * True if less than or equal: (P[i] <= M) (P[i] not_greater than M) + * Change to: (M >= P[i]) (M not_less than P[i]) + */ + status = + acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj, + &logical_result); + if (ACPI_FAILURE(status)) { + return (FALSE); + } + logical_result = (u8) ! logical_result; + break; + + case MATCH_MLT: + + /* + * True if less than: (P[i] < M) + * Change to: (M > P[i]) + */ + status = + acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj, + package_obj, &logical_result); + if (ACPI_FAILURE(status)) { + return (FALSE); + } + break; + + case MATCH_MGE: + + /* + * True if greater than or equal: (P[i] >= M) (P[i] not_less than M) + * Change to: (M <= P[i]) (M not_greater than P[i]) + */ + status = + acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj, + package_obj, &logical_result); + if (ACPI_FAILURE(status)) { + return (FALSE); + } + logical_result = (u8) ! logical_result; + break; + + case MATCH_MGT: + + /* + * True if greater than: (P[i] > M) + * Change to: (M < P[i]) + */ + status = + acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj, + &logical_result); + if (ACPI_FAILURE(status)) { + return (FALSE); + } + break; + + default: + + /* Undefined */ + + return (FALSE); + } + + return logical_result; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_6A_0T_1R + * + * PARAMETERS: walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Execute opcode with 6 arguments, no target, and a return value + * + ******************************************************************************/ + +acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) +{ + union acpi_operand_object **operand = &walk_state->operands[0]; + union acpi_operand_object *return_desc = NULL; + acpi_status status = AE_OK; + acpi_integer index; + union acpi_operand_object *this_element; + + ACPI_FUNCTION_TRACE_STR(ex_opcode_6A_0T_1R, + acpi_ps_get_opcode_name(walk_state->opcode)); + + switch (walk_state->opcode) { + case AML_MATCH_OP: + /* + * Match (search_pkg[0], match_op1[1], match_obj1[2], + * match_op2[3], match_obj2[4], start_index[5]) + */ + + /* Validate both Match Term Operators (MTR, MEQ, etc.) */ + + if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) || + (operand[3]->integer.value > MAX_MATCH_OPERATOR)) { + ACPI_ERROR((AE_INFO, "Match operator out of range")); + status = AE_AML_OPERAND_VALUE; + goto cleanup; + } + + /* Get the package start_index, validate against the package length */ + + index = operand[5]->integer.value; + if (index >= operand[0]->package.count) { + ACPI_ERROR((AE_INFO, + "Index (%X%8.8X) beyond package end (%X)", + ACPI_FORMAT_UINT64(index), + operand[0]->package.count)); + status = AE_AML_PACKAGE_LIMIT; + goto cleanup; + } + + /* Create an integer for the return value */ + + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + + } + + /* Default return value if no match found */ + + return_desc->integer.value = ACPI_INTEGER_MAX; + + /* + * Examine each element until a match is found. Both match conditions + * must be satisfied for a match to occur. Within the loop, + * "continue" signifies that the current element does not match + * and the next should be examined. + * + * Upon finding a match, the loop will terminate via "break" at + * the bottom. If it terminates "normally", match_value will be + * ACPI_INTEGER_MAX (Ones) (its initial value) indicating that no + * match was found. + */ + for (; index < operand[0]->package.count; index++) { + + /* Get the current package element */ + + this_element = operand[0]->package.elements[index]; + + /* Treat any uninitialized (NULL) elements as non-matching */ + + if (!this_element) { + continue; + } + + /* + * Both match conditions must be satisfied. Execution of a continue + * (proceed to next iteration of enclosing for loop) signifies a + * non-match. + */ + if (!acpi_ex_do_match((u32) operand[1]->integer.value, + this_element, operand[2])) { + continue; + } + + if (!acpi_ex_do_match((u32) operand[3]->integer.value, + this_element, operand[4])) { + continue; + } + + /* Match found: Index is the return value */ + + return_desc->integer.value = index; + break; + } + break; + + case AML_LOAD_TABLE_OP: + + status = acpi_ex_load_table_op(walk_state, &return_desc); + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + cleanup: + + /* Delete return object on error */ + + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(return_desc); + } + + /* Save return object on success */ + + else { + walk_state->result_obj = return_desc; + } + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c new file mode 100644 index 000000000000..8f2baa934e95 --- /dev/null +++ b/drivers/acpi/acpica/exprep.c @@ -0,0 +1,590 @@ + +/****************************************************************************** + * + * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exprep") + +/* Local prototypes */ +static u32 +acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, + u8 field_flags, u32 * return_byte_alignment); + +#ifdef ACPI_UNDER_DEVELOPMENT + +static u32 +acpi_ex_generate_access(u32 field_bit_offset, + u32 field_bit_length, u32 region_length); + +/******************************************************************************* + * + * FUNCTION: acpi_ex_generate_access + * + * PARAMETERS: field_bit_offset - Start of field within parent region/buffer + * field_bit_length - Length of field in bits + * region_length - Length of parent in bytes + * + * RETURN: Field granularity (8, 16, 32 or 64) and + * byte_alignment (1, 2, 3, or 4) + * + * DESCRIPTION: Generate an optimal access width for fields defined with the + * any_acc keyword. + * + * NOTE: Need to have the region_length in order to check for boundary + * conditions (end-of-region). However, the region_length is a deferred + * operation. Therefore, to complete this implementation, the generation + * of this access width must be deferred until the region length has + * been evaluated. + * + ******************************************************************************/ + +static u32 +acpi_ex_generate_access(u32 field_bit_offset, + u32 field_bit_length, u32 region_length) +{ + u32 field_byte_length; + u32 field_byte_offset; + u32 field_byte_end_offset; + u32 access_byte_width; + u32 field_start_offset; + u32 field_end_offset; + u32 minimum_access_width = 0xFFFFFFFF; + u32 minimum_accesses = 0xFFFFFFFF; + u32 accesses; + + ACPI_FUNCTION_TRACE(ex_generate_access); + + /* Round Field start offset and length to "minimal" byte boundaries */ + + field_byte_offset = ACPI_DIV_8(ACPI_ROUND_DOWN(field_bit_offset, 8)); + field_byte_end_offset = ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length + + field_bit_offset, 8)); + field_byte_length = field_byte_end_offset - field_byte_offset; + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Bit length %d, Bit offset %d\n", + field_bit_length, field_bit_offset)); + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Byte Length %d, Byte Offset %d, End Offset %d\n", + field_byte_length, field_byte_offset, + field_byte_end_offset)); + + /* + * Iterative search for the maximum access width that is both aligned + * and does not go beyond the end of the region + * + * Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes) + */ + for (access_byte_width = 1; access_byte_width <= 8; + access_byte_width <<= 1) { + /* + * 1) Round end offset up to next access boundary and make sure that + * this does not go beyond the end of the parent region. + * 2) When the Access width is greater than the field_byte_length, we + * are done. (This does not optimize for the perfectly aligned + * case yet). + */ + if (ACPI_ROUND_UP(field_byte_end_offset, access_byte_width) <= + region_length) { + field_start_offset = + ACPI_ROUND_DOWN(field_byte_offset, + access_byte_width) / + access_byte_width; + + field_end_offset = + ACPI_ROUND_UP((field_byte_length + + field_byte_offset), + access_byte_width) / + access_byte_width; + + accesses = field_end_offset - field_start_offset; + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "AccessWidth %d end is within region\n", + access_byte_width)); + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Field Start %d, Field End %d -- requires %d accesses\n", + field_start_offset, field_end_offset, + accesses)); + + /* Single access is optimal */ + + if (accesses <= 1) { + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Entire field can be accessed with one operation of size %d\n", + access_byte_width)); + return_VALUE(access_byte_width); + } + + /* + * Fits in the region, but requires more than one read/write. + * try the next wider access on next iteration + */ + if (accesses < minimum_accesses) { + minimum_accesses = accesses; + minimum_access_width = access_byte_width; + } + } else { + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "AccessWidth %d end is NOT within region\n", + access_byte_width)); + if (access_byte_width == 1) { + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Field goes beyond end-of-region!\n")); + + /* Field does not fit in the region at all */ + + return_VALUE(0); + } + + /* + * This width goes beyond the end-of-region, back off to + * previous access + */ + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Backing off to previous optimal access width of %d\n", + minimum_access_width)); + return_VALUE(minimum_access_width); + } + } + + /* + * Could not read/write field with one operation, + * just use max access width + */ + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Cannot access field in one operation, using width 8\n")); + return_VALUE(8); +} +#endif /* ACPI_UNDER_DEVELOPMENT */ + +/******************************************************************************* + * + * FUNCTION: acpi_ex_decode_field_access + * + * PARAMETERS: obj_desc - Field object + * field_flags - Encoded fieldflags (contains access bits) + * return_byte_alignment - Where the byte alignment is returned + * + * RETURN: Field granularity (8, 16, 32 or 64) and + * byte_alignment (1, 2, 3, or 4) + * + * DESCRIPTION: Decode the access_type bits of a field definition. + * + ******************************************************************************/ + +static u32 +acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, + u8 field_flags, u32 * return_byte_alignment) +{ + u32 access; + u32 byte_alignment; + u32 bit_length; + + ACPI_FUNCTION_TRACE(ex_decode_field_access); + + access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK); + + switch (access) { + case AML_FIELD_ACCESS_ANY: + +#ifdef ACPI_UNDER_DEVELOPMENT + byte_alignment = + acpi_ex_generate_access(obj_desc->common_field. + start_field_bit_offset, + obj_desc->common_field.bit_length, + 0xFFFFFFFF + /* Temp until we pass region_length as parameter */ + ); + bit_length = byte_alignment * 8; +#endif + + byte_alignment = 1; + bit_length = 8; + break; + + case AML_FIELD_ACCESS_BYTE: + case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */ + byte_alignment = 1; + bit_length = 8; + break; + + case AML_FIELD_ACCESS_WORD: + byte_alignment = 2; + bit_length = 16; + break; + + case AML_FIELD_ACCESS_DWORD: + byte_alignment = 4; + bit_length = 32; + break; + + case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ + byte_alignment = 8; + bit_length = 64; + break; + + default: + /* Invalid field access type */ + + ACPI_ERROR((AE_INFO, "Unknown field access type %X", access)); + return_UINT32(0); + } + + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { + /* + * buffer_field access can be on any byte boundary, so the + * byte_alignment is always 1 byte -- regardless of any byte_alignment + * implied by the field access type. + */ + byte_alignment = 1; + } + + *return_byte_alignment = byte_alignment; + return_UINT32(bit_length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_prep_common_field_object + * + * PARAMETERS: obj_desc - The field object + * field_flags - Access, lock_rule, and update_rule. + * The format of a field_flag is described + * in the ACPI specification + * field_attribute - Special attributes (not used) + * field_bit_position - Field start position + * field_bit_length - Field length in number of bits + * + * RETURN: Status + * + * DESCRIPTION: Initialize the areas of the field object that are common + * to the various types of fields. Note: This is very "sensitive" + * code because we are solving the general case for field + * alignment. + * + ******************************************************************************/ + +acpi_status +acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, + u8 field_flags, + u8 field_attribute, + u32 field_bit_position, u32 field_bit_length) +{ + u32 access_bit_width; + u32 byte_alignment; + u32 nearest_byte_address; + + ACPI_FUNCTION_TRACE(ex_prep_common_field_object); + + /* + * Note: the structure being initialized is the + * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common + * area are initialized by this procedure. + */ + obj_desc->common_field.field_flags = field_flags; + obj_desc->common_field.attribute = field_attribute; + obj_desc->common_field.bit_length = field_bit_length; + + /* + * Decode the access type so we can compute offsets. The access type gives + * two pieces of information - the width of each field access and the + * necessary byte_alignment (address granularity) of the access. + * + * For any_acc, the access_bit_width is the largest width that is both + * necessary and possible in an attempt to access the whole field in one + * I/O operation. However, for any_acc, the byte_alignment is always one + * byte. + * + * For all Buffer Fields, the byte_alignment is always one byte. + * + * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is + * the same (equivalent) as the byte_alignment. + */ + access_bit_width = acpi_ex_decode_field_access(obj_desc, field_flags, + &byte_alignment); + if (!access_bit_width) { + return_ACPI_STATUS(AE_AML_OPERAND_VALUE); + } + + /* Setup width (access granularity) fields */ + + obj_desc->common_field.access_byte_width = (u8) + ACPI_DIV_8(access_bit_width); /* 1, 2, 4, 8 */ + + obj_desc->common_field.access_bit_width = (u8) access_bit_width; + + /* + * base_byte_offset is the address of the start of the field within the + * region. It is the byte address of the first *datum* (field-width data + * unit) of the field. (i.e., the first datum that contains at least the + * first *bit* of the field.) + * + * Note: byte_alignment is always either equal to the access_bit_width or 8 + * (Byte access), and it defines the addressing granularity of the parent + * region or buffer. + */ + nearest_byte_address = + ACPI_ROUND_BITS_DOWN_TO_BYTES(field_bit_position); + obj_desc->common_field.base_byte_offset = (u32) + ACPI_ROUND_DOWN(nearest_byte_address, byte_alignment); + + /* + * start_field_bit_offset is the offset of the first bit of the field within + * a field datum. + */ + obj_desc->common_field.start_field_bit_offset = (u8) + (field_bit_position - + ACPI_MUL_8(obj_desc->common_field.base_byte_offset)); + + /* + * Does the entire field fit within a single field access element? (datum) + * (i.e., without crossing a datum boundary) + */ + if ((obj_desc->common_field.start_field_bit_offset + + field_bit_length) <= (u16) access_bit_width) { + obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_prep_field_value + * + * PARAMETERS: Info - Contains all field creation info + * + * RETURN: Status + * + * DESCRIPTION: Construct an union acpi_operand_object of type def_field and + * connect it to the parent Node. + * + ******************************************************************************/ + +acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *second_desc = NULL; + u32 type; + acpi_status status; + + ACPI_FUNCTION_TRACE(ex_prep_field_value); + + /* Parameter validation */ + + if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) { + if (!info->region_node) { + ACPI_ERROR((AE_INFO, "Null RegionNode")); + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + type = acpi_ns_get_type(info->region_node); + if (type != ACPI_TYPE_REGION) { + ACPI_ERROR((AE_INFO, + "Needed Region, found type %X (%s)", + type, acpi_ut_get_type_name(type))); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + } + + /* Allocate a new field object */ + + obj_desc = acpi_ut_create_internal_object(info->field_type); + if (!obj_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Initialize areas of the object that are common to all fields */ + + obj_desc->common_field.node = info->field_node; + status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags, + info->attribute, + info->field_bit_position, + info->field_bit_length); + if (ACPI_FAILURE(status)) { + acpi_ut_delete_object_desc(obj_desc); + return_ACPI_STATUS(status); + } + + /* Initialize areas of the object that are specific to the field type */ + + switch (info->field_type) { + case ACPI_TYPE_LOCAL_REGION_FIELD: + + obj_desc->field.region_obj = + acpi_ns_get_attached_object(info->region_node); + + /* An additional reference for the container */ + + acpi_ut_add_reference(obj_desc->field.region_obj); + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", + obj_desc->field.start_field_bit_offset, + obj_desc->field.base_byte_offset, + obj_desc->field.access_byte_width, + obj_desc->field.region_obj)); + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + obj_desc->bank_field.value = info->bank_value; + obj_desc->bank_field.region_obj = + acpi_ns_get_attached_object(info->region_node); + obj_desc->bank_field.bank_obj = + acpi_ns_get_attached_object(info->register_node); + + /* An additional reference for the attached objects */ + + acpi_ut_add_reference(obj_desc->bank_field.region_obj); + acpi_ut_add_reference(obj_desc->bank_field.bank_obj); + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n", + obj_desc->bank_field.start_field_bit_offset, + obj_desc->bank_field.base_byte_offset, + obj_desc->field.access_byte_width, + obj_desc->bank_field.region_obj, + obj_desc->bank_field.bank_obj)); + + /* + * Remember location in AML stream of the field unit + * opcode and operands -- since the bank_value + * operands must be evaluated. + */ + second_desc = obj_desc->common.next_object; + second_desc->extra.aml_start = + ACPI_CAST_PTR(union acpi_parse_object, + info->data_register_node)->named.data; + second_desc->extra.aml_length = + ACPI_CAST_PTR(union acpi_parse_object, + info->data_register_node)->named.length; + + break; + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + /* Get the Index and Data registers */ + + obj_desc->index_field.index_obj = + acpi_ns_get_attached_object(info->register_node); + obj_desc->index_field.data_obj = + acpi_ns_get_attached_object(info->data_register_node); + + if (!obj_desc->index_field.data_obj + || !obj_desc->index_field.index_obj) { + ACPI_ERROR((AE_INFO, + "Null Index Object during field prep")); + acpi_ut_delete_object_desc(obj_desc); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + /* An additional reference for the attached objects */ + + acpi_ut_add_reference(obj_desc->index_field.data_obj); + acpi_ut_add_reference(obj_desc->index_field.index_obj); + + /* + * April 2006: Changed to match MS behavior + * + * The value written to the Index register is the byte offset of the + * target field in units of the granularity of the index_field + * + * Previously, the value was calculated as an index in terms of the + * width of the Data register, as below: + * + * obj_desc->index_field.Value = (u32) + * (Info->field_bit_position / ACPI_MUL_8 ( + * obj_desc->Field.access_byte_width)); + * + * February 2006: Tried value as a byte offset: + * obj_desc->index_field.Value = (u32) + * ACPI_DIV_8 (Info->field_bit_position); + */ + obj_desc->index_field.value = + (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position), + obj_desc->index_field. + access_byte_width); + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", + obj_desc->index_field.start_field_bit_offset, + obj_desc->index_field.base_byte_offset, + obj_desc->index_field.value, + obj_desc->field.access_byte_width, + obj_desc->index_field.index_obj, + obj_desc->index_field.data_obj)); + break; + + default: + /* No other types should get here */ + break; + } + + /* + * Store the constructed descriptor (obj_desc) into the parent Node, + * preserving the current type of that named_obj. + */ + status = acpi_ns_attach_object(info->field_node, obj_desc, + acpi_ns_get_type(info->field_node)); + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "Set NamedObj %p [%4.4s], ObjDesc %p\n", + info->field_node, + acpi_ut_get_node_name(info->field_node), obj_desc)); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c new file mode 100644 index 000000000000..ceb269e45aba --- /dev/null +++ b/drivers/acpi/acpica/exregion.c @@ -0,0 +1,499 @@ + +/****************************************************************************** + * + * Module Name: exregion - ACPI default op_region (address space) handlers + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exregion") + +/******************************************************************************* + * + * FUNCTION: acpi_ex_system_memory_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * handler_context - Pointer to Handler's context + * region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the System Memory address space (Op Region) + * + ******************************************************************************/ +acpi_status +acpi_ex_system_memory_space_handler(u32 function, + acpi_physical_address address, + u32 bit_width, + acpi_integer * value, + void *handler_context, void *region_context) +{ + acpi_status status = AE_OK; + void *logical_addr_ptr = NULL; + struct acpi_mem_space_context *mem_info = region_context; + u32 length; + acpi_size window_size; +#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED + u32 remainder; +#endif + + ACPI_FUNCTION_TRACE(ex_system_memory_space_handler); + + /* Validate and translate the bit width */ + + switch (bit_width) { + case 8: + length = 1; + break; + + case 16: + length = 2; + break; + + case 32: + length = 4; + break; + + case 64: + length = 8; + break; + + default: + ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %d", + bit_width)); + return_ACPI_STATUS(AE_AML_OPERAND_VALUE); + } + +#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED + /* + * Hardware does not support non-aligned data transfers, we must verify + * the request. + */ + (void)acpi_ut_short_divide((acpi_integer) address, length, NULL, + &remainder); + if (remainder != 0) { + return_ACPI_STATUS(AE_AML_ALIGNMENT); + } +#endif + + /* + * Does the request fit into the cached memory mapping? + * Is 1) Address below the current mapping? OR + * 2) Address beyond the current mapping? + */ + if ((address < mem_info->mapped_physical_address) || + (((acpi_integer) address + length) > ((acpi_integer) + mem_info-> + mapped_physical_address + + mem_info->mapped_length))) { + /* + * The request cannot be resolved by the current memory mapping; + * Delete the existing mapping and create a new one. + */ + if (mem_info->mapped_length) { + + /* Valid mapping, delete it */ + + acpi_os_unmap_memory(mem_info->mapped_logical_address, + mem_info->mapped_length); + } + + /* + * Don't attempt to map memory beyond the end of the region, and + * constrain the maximum mapping size to something reasonable. + */ + window_size = (acpi_size) + ((mem_info->address + mem_info->length) - address); + + if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) { + window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE; + } + + /* Create a new mapping starting at the address given */ + + mem_info->mapped_logical_address = + acpi_os_map_memory((acpi_physical_address) address, window_size); + if (!mem_info->mapped_logical_address) { + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X%8.8X, size %X", + ACPI_FORMAT_NATIVE_UINT(address), + (u32) window_size)); + mem_info->mapped_length = 0; + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Save the physical address and mapping size */ + + mem_info->mapped_physical_address = address; + mem_info->mapped_length = window_size; + } + + /* + * Generate a logical pointer corresponding to the address we want to + * access + */ + logical_addr_ptr = mem_info->mapped_logical_address + + ((acpi_integer) address - + (acpi_integer) mem_info->mapped_physical_address); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", + bit_width, function, + ACPI_FORMAT_NATIVE_UINT(address))); + + /* + * Perform the memory read or write + * + * Note: For machines that do not support non-aligned transfers, the target + * address was checked for alignment above. We do not attempt to break the + * transfer up into smaller (byte-size) chunks because the AML specifically + * asked for a transfer width that the hardware may require. + */ + switch (function) { + case ACPI_READ: + + *value = 0; + switch (bit_width) { + case 8: + *value = (acpi_integer) ACPI_GET8(logical_addr_ptr); + break; + + case 16: + *value = (acpi_integer) ACPI_GET16(logical_addr_ptr); + break; + + case 32: + *value = (acpi_integer) ACPI_GET32(logical_addr_ptr); + break; + + case 64: + *value = (acpi_integer) ACPI_GET64(logical_addr_ptr); + break; + + default: + /* bit_width was already validated */ + break; + } + break; + + case ACPI_WRITE: + + switch (bit_width) { + case 8: + ACPI_SET8(logical_addr_ptr) = (u8) * value; + break; + + case 16: + ACPI_SET16(logical_addr_ptr) = (u16) * value; + break; + + case 32: + ACPI_SET32(logical_addr_ptr) = (u32) * value; + break; + + case 64: + ACPI_SET64(logical_addr_ptr) = (u64) * value; + break; + + default: + /* bit_width was already validated */ + break; + } + break; + + default: + status = AE_BAD_PARAMETER; + break; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_system_io_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * handler_context - Pointer to Handler's context + * region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the System IO address space (Op Region) + * + ******************************************************************************/ + +acpi_status +acpi_ex_system_io_space_handler(u32 function, + acpi_physical_address address, + u32 bit_width, + acpi_integer * value, + void *handler_context, void *region_context) +{ + acpi_status status = AE_OK; + u32 value32; + + ACPI_FUNCTION_TRACE(ex_system_io_space_handler); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", + bit_width, function, + ACPI_FORMAT_NATIVE_UINT(address))); + + /* Decode the function parameter */ + + switch (function) { + case ACPI_READ: + + status = acpi_os_read_port((acpi_io_address) address, + &value32, bit_width); + *value = value32; + break; + + case ACPI_WRITE: + + status = acpi_os_write_port((acpi_io_address) address, + (u32) * value, bit_width); + break; + + default: + status = AE_BAD_PARAMETER; + break; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_pci_config_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * handler_context - Pointer to Handler's context + * region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the PCI Config address space (Op Region) + * + ******************************************************************************/ + +acpi_status +acpi_ex_pci_config_space_handler(u32 function, + acpi_physical_address address, + u32 bit_width, + acpi_integer * value, + void *handler_context, void *region_context) +{ + acpi_status status = AE_OK; + struct acpi_pci_id *pci_id; + u16 pci_register; + u32 value32; + + ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); + + /* + * The arguments to acpi_os(Read|Write)pci_configuration are: + * + * pci_segment is the PCI bus segment range 0-31 + * pci_bus is the PCI bus number range 0-255 + * pci_device is the PCI device number range 0-31 + * pci_function is the PCI device function number + * pci_register is the Config space register range 0-255 bytes + * + * Value - input value for write, output address for read + * + */ + pci_id = (struct acpi_pci_id *)region_context; + pci_register = (u16) (u32) address; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Pci-Config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", + function, bit_width, pci_id->segment, pci_id->bus, + pci_id->device, pci_id->function, pci_register)); + + switch (function) { + case ACPI_READ: + + status = acpi_os_read_pci_configuration(pci_id, pci_register, + &value32, bit_width); + *value = value32; + break; + + case ACPI_WRITE: + + status = acpi_os_write_pci_configuration(pci_id, pci_register, + *value, bit_width); + break; + + default: + + status = AE_BAD_PARAMETER; + break; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_cmos_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * handler_context - Pointer to Handler's context + * region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the CMOS address space (Op Region) + * + ******************************************************************************/ + +acpi_status +acpi_ex_cmos_space_handler(u32 function, + acpi_physical_address address, + u32 bit_width, + acpi_integer * value, + void *handler_context, void *region_context) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_cmos_space_handler); + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_pci_bar_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * handler_context - Pointer to Handler's context + * region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the PCI bar_target address space (Op Region) + * + ******************************************************************************/ + +acpi_status +acpi_ex_pci_bar_space_handler(u32 function, + acpi_physical_address address, + u32 bit_width, + acpi_integer * value, + void *handler_context, void *region_context) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler); + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_data_table_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * handler_context - Pointer to Handler's context + * region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the Data Table address space (Op Region) + * + ******************************************************************************/ + +acpi_status +acpi_ex_data_table_space_handler(u32 function, + acpi_physical_address address, + u32 bit_width, + acpi_integer * value, + void *handler_context, void *region_context) +{ + ACPI_FUNCTION_TRACE(ex_data_table_space_handler); + + /* Perform the memory read or write */ + + switch (function) { + case ACPI_READ: + + ACPI_MEMCPY(ACPI_CAST_PTR(char, value), + ACPI_PHYSADDR_TO_PTR(address), + ACPI_DIV_8(bit_width)); + break; + + case ACPI_WRITE: + default: + + return_ACPI_STATUS(AE_SUPPORT); + } + + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c new file mode 100644 index 000000000000..77df6e490e70 --- /dev/null +++ b/drivers/acpi/acpica/exresnte.c @@ -0,0 +1,278 @@ + +/****************************************************************************** + * + * Module Name: exresnte - AML Interpreter object resolution + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exresnte") + +/******************************************************************************* + * + * FUNCTION: acpi_ex_resolve_node_to_value + * + * PARAMETERS: object_ptr - Pointer to a location that contains + * a pointer to a NS node, and will receive a + * pointer to the resolved object. + * walk_state - Current state. Valid only if executing AML + * code. NULL if simply resolving an object + * + * RETURN: Status + * + * DESCRIPTION: Resolve a Namespace node to a valued object + * + * Note: for some of the data types, the pointer attached to the Node + * can be either a pointer to an actual internal object or a pointer into the + * AML stream itself. These types are currently: + * + * ACPI_TYPE_INTEGER + * ACPI_TYPE_STRING + * ACPI_TYPE_BUFFER + * ACPI_TYPE_MUTEX + * ACPI_TYPE_PACKAGE + * + ******************************************************************************/ +acpi_status +acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, + struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_operand_object *source_desc; + union acpi_operand_object *obj_desc = NULL; + struct acpi_namespace_node *node; + acpi_object_type entry_type; + + ACPI_FUNCTION_TRACE(ex_resolve_node_to_value); + + /* + * The stack pointer points to a struct acpi_namespace_node (Node). Get the + * object that is attached to the Node. + */ + node = *object_ptr; + source_desc = acpi_ns_get_attached_object(node); + entry_type = acpi_ns_get_type((acpi_handle) node); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n", + node, source_desc, + acpi_ut_get_type_name(entry_type))); + + if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) || + (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { + + /* There is always exactly one level of indirection */ + + node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object); + source_desc = acpi_ns_get_attached_object(node); + entry_type = acpi_ns_get_type((acpi_handle) node); + *object_ptr = node; + } + + /* + * Several object types require no further processing: + * 1) Device/Thermal objects don't have a "real" subobject, return the Node + * 2) Method locals and arguments have a pseudo-Node + * 3) 10/2007: Added method type to assist with Package construction. + */ + if ((entry_type == ACPI_TYPE_DEVICE) || + (entry_type == ACPI_TYPE_THERMAL) || + (entry_type == ACPI_TYPE_METHOD) || + (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { + return_ACPI_STATUS(AE_OK); + } + + if (!source_desc) { + ACPI_ERROR((AE_INFO, "No object attached to node %p", node)); + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + /* + * Action is based on the type of the Node, which indicates the type + * of the attached object or pointer + */ + switch (entry_type) { + case ACPI_TYPE_PACKAGE: + + if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_PACKAGE) { + ACPI_ERROR((AE_INFO, "Object not a Package, type %s", + acpi_ut_get_object_type_name(source_desc))); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + status = acpi_ds_get_package_arguments(source_desc); + if (ACPI_SUCCESS(status)) { + + /* Return an additional reference to the object */ + + obj_desc = source_desc; + acpi_ut_add_reference(obj_desc); + } + break; + + case ACPI_TYPE_BUFFER: + + if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) { + ACPI_ERROR((AE_INFO, "Object not a Buffer, type %s", + acpi_ut_get_object_type_name(source_desc))); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + status = acpi_ds_get_buffer_arguments(source_desc); + if (ACPI_SUCCESS(status)) { + + /* Return an additional reference to the object */ + + obj_desc = source_desc; + acpi_ut_add_reference(obj_desc); + } + break; + + case ACPI_TYPE_STRING: + + if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) { + ACPI_ERROR((AE_INFO, "Object not a String, type %s", + acpi_ut_get_object_type_name(source_desc))); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = source_desc; + acpi_ut_add_reference(obj_desc); + break; + + case ACPI_TYPE_INTEGER: + + if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) { + ACPI_ERROR((AE_INFO, "Object not a Integer, type %s", + acpi_ut_get_object_type_name(source_desc))); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = source_desc; + acpi_ut_add_reference(obj_desc); + break; + + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "FieldRead Node=%p SourceDesc=%p Type=%X\n", + node, source_desc, entry_type)); + + status = + acpi_ex_read_data_from_field(walk_state, source_desc, + &obj_desc); + break; + + /* For these objects, just return the object attached to the Node */ + + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_REGION: + + /* Return an additional reference to the object */ + + obj_desc = source_desc; + acpi_ut_add_reference(obj_desc); + break; + + /* TYPE_ANY is untyped, and thus there is no object associated with it */ + + case ACPI_TYPE_ANY: + + ACPI_ERROR((AE_INFO, + "Untyped entry %p, no attached object!", node)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */ + + case ACPI_TYPE_LOCAL_REFERENCE: + + switch (source_desc->reference.class) { + case ACPI_REFCLASS_TABLE: /* This is a ddb_handle */ + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_INDEX: + + /* Return an additional reference to the object */ + + obj_desc = source_desc; + acpi_ut_add_reference(obj_desc); + break; + + default: + /* No named references are allowed here */ + + ACPI_ERROR((AE_INFO, + "Unsupported Reference type %X", + source_desc->reference.class)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + break; + + default: + + /* Default case is for unknown types */ + + ACPI_ERROR((AE_INFO, + "Node %p - Unknown object type %X", + node, entry_type)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + + } /* switch (entry_type) */ + + /* Return the object descriptor */ + + *object_ptr = (void *)obj_desc; + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c new file mode 100644 index 000000000000..42adde01bc93 --- /dev/null +++ b/drivers/acpi/acpica/exresolv.c @@ -0,0 +1,551 @@ + +/****************************************************************************** + * + * Module Name: exresolv - AML Interpreter object resolution + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exresolv") + +/* Local prototypes */ +static acpi_status +acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, + struct acpi_walk_state *walk_state); + +/******************************************************************************* + * + * FUNCTION: acpi_ex_resolve_to_value + * + * PARAMETERS: **stack_ptr - Points to entry on obj_stack, which can + * be either an (union acpi_operand_object *) + * or an acpi_handle. + * walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Convert Reference objects to values + * + ******************************************************************************/ + +acpi_status +acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr); + + if (!stack_ptr || !*stack_ptr) { + ACPI_ERROR((AE_INFO, "Internal - null pointer")); + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + /* + * The entity pointed to by the stack_ptr can be either + * 1) A valid union acpi_operand_object, or + * 2) A struct acpi_namespace_node (named_obj) + */ + if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) { + status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (!*stack_ptr) { + ACPI_ERROR((AE_INFO, "Internal - null pointer")); + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + } + + /* + * Object on the stack may have changed if acpi_ex_resolve_object_to_value() + * was called (i.e., we can't use an _else_ here.) + */ + if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) { + status = + acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR + (struct acpi_namespace_node, + stack_ptr), walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr)); + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_resolve_object_to_value + * + * PARAMETERS: stack_ptr - Pointer to an internal object + * walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value from an internal object. The Reference type + * uses the associated AML opcode to determine the value. + * + ******************************************************************************/ + +static acpi_status +acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, + struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_operand_object *stack_desc; + union acpi_operand_object *obj_desc = NULL; + u8 ref_type; + + ACPI_FUNCTION_TRACE(ex_resolve_object_to_value); + + stack_desc = *stack_ptr; + + /* This is an union acpi_operand_object */ + + switch (ACPI_GET_OBJECT_TYPE(stack_desc)) { + case ACPI_TYPE_LOCAL_REFERENCE: + + ref_type = stack_desc->reference.class; + + switch (ref_type) { + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + + /* + * Get the local from the method's state info + * Note: this increments the local's object reference count + */ + status = acpi_ds_method_data_get_value(ref_type, + stack_desc-> + reference.value, + walk_state, + &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Arg/Local %X] ValueObj is %p\n", + stack_desc->reference.value, + obj_desc)); + + /* + * Now we can delete the original Reference Object and + * replace it with the resolved value + */ + acpi_ut_remove_reference(stack_desc); + *stack_ptr = obj_desc; + break; + + case ACPI_REFCLASS_INDEX: + + switch (stack_desc->reference.target_type) { + case ACPI_TYPE_BUFFER_FIELD: + + /* Just return - do not dereference */ + break; + + case ACPI_TYPE_PACKAGE: + + /* If method call or copy_object - do not dereference */ + + if ((walk_state->opcode == + AML_INT_METHODCALL_OP) + || (walk_state->opcode == AML_COPY_OP)) { + break; + } + + /* Otherwise, dereference the package_index to a package element */ + + obj_desc = *stack_desc->reference.where; + if (obj_desc) { + /* + * Valid object descriptor, copy pointer to return value + * (i.e., dereference the package index) + * Delete the ref object, increment the returned object + */ + acpi_ut_remove_reference(stack_desc); + acpi_ut_add_reference(obj_desc); + *stack_ptr = obj_desc; + } else { + /* + * A NULL object descriptor means an uninitialized element of + * the package, can't dereference it + */ + ACPI_ERROR((AE_INFO, + "Attempt to dereference an Index to NULL package element Idx=%p", + stack_desc)); + status = AE_AML_UNINITIALIZED_ELEMENT; + } + break; + + default: + + /* Invalid reference object */ + + ACPI_ERROR((AE_INFO, + "Unknown TargetType %X in Index/Reference object %p", + stack_desc->reference.target_type, + stack_desc)); + status = AE_AML_INTERNAL; + break; + } + break; + + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_DEBUG: + case ACPI_REFCLASS_TABLE: + + /* Just leave the object as-is, do not dereference */ + + break; + + case ACPI_REFCLASS_NAME: /* Reference to a named object */ + + /* Dereference the name */ + + if ((stack_desc->reference.node->type == + ACPI_TYPE_DEVICE) + || (stack_desc->reference.node->type == + ACPI_TYPE_THERMAL)) { + + /* These node types do not have 'real' subobjects */ + + *stack_ptr = (void *)stack_desc->reference.node; + } else { + /* Get the object pointed to by the namespace node */ + + *stack_ptr = + (stack_desc->reference.node)->object; + acpi_ut_add_reference(*stack_ptr); + } + + acpi_ut_remove_reference(stack_desc); + break; + + default: + + ACPI_ERROR((AE_INFO, + "Unknown Reference type %X in %p", ref_type, + stack_desc)); + status = AE_AML_INTERNAL; + break; + } + break; + + case ACPI_TYPE_BUFFER: + + status = acpi_ds_get_buffer_arguments(stack_desc); + break; + + case ACPI_TYPE_PACKAGE: + + status = acpi_ds_get_package_arguments(stack_desc); + break; + + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "FieldRead SourceDesc=%p Type=%X\n", + stack_desc, + ACPI_GET_OBJECT_TYPE(stack_desc))); + + status = + acpi_ex_read_data_from_field(walk_state, stack_desc, + &obj_desc); + + /* Remove a reference to the original operand, then override */ + + acpi_ut_remove_reference(*stack_ptr); + *stack_ptr = (void *)obj_desc; + break; + + default: + break; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_resolve_multiple + * + * PARAMETERS: walk_state - Current state (contains AML opcode) + * Operand - Starting point for resolution + * return_type - Where the object type is returned + * return_desc - Where the resolved object is returned + * + * RETURN: Status + * + * DESCRIPTION: Return the base object and type. Traverse a reference list if + * necessary to get to the base object. + * + ******************************************************************************/ + +acpi_status +acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, + union acpi_operand_object *operand, + acpi_object_type * return_type, + union acpi_operand_object **return_desc) +{ + union acpi_operand_object *obj_desc = (void *)operand; + struct acpi_namespace_node *node; + acpi_object_type type; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple); + + /* Operand can be either a namespace node or an operand descriptor */ + + switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { + case ACPI_DESC_TYPE_OPERAND: + type = obj_desc->common.type; + break; + + case ACPI_DESC_TYPE_NAMED: + type = ((struct acpi_namespace_node *)obj_desc)->type; + obj_desc = + acpi_ns_get_attached_object((struct acpi_namespace_node *) + obj_desc); + + /* If we had an Alias node, use the attached object for type info */ + + if (type == ACPI_TYPE_LOCAL_ALIAS) { + type = ((struct acpi_namespace_node *)obj_desc)->type; + obj_desc = + acpi_ns_get_attached_object((struct + acpi_namespace_node *) + obj_desc); + } + break; + + default: + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* If type is anything other than a reference, we are done */ + + if (type != ACPI_TYPE_LOCAL_REFERENCE) { + goto exit; + } + + /* + * For reference objects created via the ref_of, Index, or Load/load_table + * operators, we need to get to the base object (as per the ACPI + * specification of the object_type and size_of operators). This means + * traversing the list of possibly many nested references. + */ + while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_NAME: + + /* Dereference the reference pointer */ + + if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) { + node = obj_desc->reference.object; + } else { /* AML_INT_NAMEPATH_OP */ + + node = obj_desc->reference.node; + } + + /* All "References" point to a NS node */ + + if (ACPI_GET_DESCRIPTOR_TYPE(node) != + ACPI_DESC_TYPE_NAMED) { + ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]", + node, + acpi_ut_get_descriptor_name(node))); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + /* Get the attached object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + + /* No object, use the NS node type */ + + type = acpi_ns_get_type(node); + goto exit; + } + + /* Check for circular references */ + + if (obj_desc == operand) { + return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE); + } + break; + + case ACPI_REFCLASS_INDEX: + + /* Get the type of this reference (index into another object) */ + + type = obj_desc->reference.target_type; + if (type != ACPI_TYPE_PACKAGE) { + goto exit; + } + + /* + * The main object is a package, we want to get the type + * of the individual package element that is referenced by + * the index. + * + * This could of course in turn be another reference object. + */ + obj_desc = *(obj_desc->reference.where); + if (!obj_desc) { + + /* NULL package elements are allowed */ + + type = 0; /* Uninitialized */ + goto exit; + } + break; + + case ACPI_REFCLASS_TABLE: + + type = ACPI_TYPE_DDB_HANDLE; + goto exit; + + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + + if (return_desc) { + status = + acpi_ds_method_data_get_value(obj_desc-> + reference. + class, + obj_desc-> + reference. + value, + walk_state, + &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + acpi_ut_remove_reference(obj_desc); + } else { + status = + acpi_ds_method_data_get_node(obj_desc-> + reference. + class, + obj_desc-> + reference. + value, + walk_state, + &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + type = ACPI_TYPE_ANY; + goto exit; + } + } + break; + + case ACPI_REFCLASS_DEBUG: + + /* The Debug Object is of type "DebugObject" */ + + type = ACPI_TYPE_DEBUG_OBJECT; + goto exit; + + default: + + ACPI_ERROR((AE_INFO, + "Unknown Reference Class %2.2X", + obj_desc->reference.class)); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + } + + /* + * Now we are guaranteed to have an object that has not been created + * via the ref_of or Index operators. + */ + type = ACPI_GET_OBJECT_TYPE(obj_desc); + + exit: + /* Convert internal types to external types */ + + switch (type) { + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + type = ACPI_TYPE_FIELD_UNIT; + break; + + case ACPI_TYPE_LOCAL_SCOPE: + + /* Per ACPI Specification, Scope is untyped */ + + type = ACPI_TYPE_ANY; + break; + + default: + /* No change to Type required */ + break; + } + + *return_type = type; + if (return_desc) { + *return_desc = obj_desc; + } + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c new file mode 100644 index 000000000000..7602eaf5c479 --- /dev/null +++ b/drivers/acpi/acpica/exresop.c @@ -0,0 +1,701 @@ + +/****************************************************************************** + * + * Module Name: exresop - AML Interpreter operand/object resolution + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exresop") + +/* Local prototypes */ +static acpi_status +acpi_ex_check_object_type(acpi_object_type type_needed, + acpi_object_type this_type, void *object); + +/******************************************************************************* + * + * FUNCTION: acpi_ex_check_object_type + * + * PARAMETERS: type_needed Object type needed + * this_type Actual object type + * Object Object pointer + * + * RETURN: Status + * + * DESCRIPTION: Check required type against actual type + * + ******************************************************************************/ + +static acpi_status +acpi_ex_check_object_type(acpi_object_type type_needed, + acpi_object_type this_type, void *object) +{ + ACPI_FUNCTION_ENTRY(); + + if (type_needed == ACPI_TYPE_ANY) { + + /* All types OK, so we don't perform any typechecks */ + + return (AE_OK); + } + + if (type_needed == ACPI_TYPE_LOCAL_REFERENCE) { + /* + * Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference + * objects and thus allow them to be targets. (As per the ACPI + * specification, a store to a constant is a noop.) + */ + if ((this_type == ACPI_TYPE_INTEGER) && + (((union acpi_operand_object *)object)->common. + flags & AOPOBJ_AML_CONSTANT)) { + return (AE_OK); + } + } + + if (type_needed != this_type) { + ACPI_ERROR((AE_INFO, + "Needed type [%s], found [%s] %p", + acpi_ut_get_type_name(type_needed), + acpi_ut_get_type_name(this_type), object)); + + return (AE_AML_OPERAND_TYPE); + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_resolve_operands + * + * PARAMETERS: Opcode - Opcode being interpreted + * stack_ptr - Pointer to the operand stack to be + * resolved + * walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Convert multiple input operands to the types required by the + * target operator. + * + * Each 5-bit group in arg_types represents one required + * operand and indicates the required Type. The corresponding operand + * will be converted to the required type if possible, otherwise we + * abort with an exception. + * + ******************************************************************************/ + +acpi_status +acpi_ex_resolve_operands(u16 opcode, + union acpi_operand_object ** stack_ptr, + struct acpi_walk_state * walk_state) +{ + union acpi_operand_object *obj_desc; + acpi_status status = AE_OK; + u8 object_type; + u32 arg_types; + const struct acpi_opcode_info *op_info; + u32 this_arg_type; + acpi_object_type type_needed; + u16 target_op = 0; + + ACPI_FUNCTION_TRACE_U32(ex_resolve_operands, opcode); + + op_info = acpi_ps_get_opcode_info(opcode); + if (op_info->class == AML_CLASS_UNKNOWN) { + return_ACPI_STATUS(AE_AML_BAD_OPCODE); + } + + arg_types = op_info->runtime_args; + if (arg_types == ARGI_INVALID_OPCODE) { + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", opcode)); + + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Opcode %X [%s] RequiredOperandTypes=%8.8X\n", + opcode, op_info->name, arg_types)); + + /* + * Normal exit is with (arg_types == 0) at end of argument list. + * Function will return an exception from within the loop upon + * finding an entry which is not (or cannot be converted + * to) the required type; if stack underflows; or upon + * finding a NULL stack entry (which should not happen). + */ + while (GET_CURRENT_ARG_TYPE(arg_types)) { + if (!stack_ptr || !*stack_ptr) { + ACPI_ERROR((AE_INFO, "Null stack entry at %p", + stack_ptr)); + + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + /* Extract useful items */ + + obj_desc = *stack_ptr; + + /* Decode the descriptor type */ + + switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { + case ACPI_DESC_TYPE_NAMED: + + /* Namespace Node */ + + object_type = + ((struct acpi_namespace_node *)obj_desc)->type; + + /* + * Resolve an alias object. The construction of these objects + * guarantees that there is only one level of alias indirection; + * thus, the attached object is always the aliased namespace node + */ + if (object_type == ACPI_TYPE_LOCAL_ALIAS) { + obj_desc = + acpi_ns_get_attached_object((struct + acpi_namespace_node + *)obj_desc); + *stack_ptr = obj_desc; + object_type = + ((struct acpi_namespace_node *)obj_desc)-> + type; + } + break; + + case ACPI_DESC_TYPE_OPERAND: + + /* ACPI internal object */ + + object_type = ACPI_GET_OBJECT_TYPE(obj_desc); + + /* Check for bad acpi_object_type */ + + if (!acpi_ut_valid_object_type(object_type)) { + ACPI_ERROR((AE_INFO, + "Bad operand object type [%X]", + object_type)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) { + + /* Validate the Reference */ + + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_DEBUG: + + target_op = AML_DEBUG_OP; + + /*lint -fallthrough */ + + case ACPI_REFCLASS_ARG: + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_INDEX: + case ACPI_REFCLASS_REFOF: + case ACPI_REFCLASS_TABLE: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */ + case ACPI_REFCLASS_NAME: /* Reference to a named object */ + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Operand is a Reference, Class [%s] %2.2X\n", + acpi_ut_get_reference_name + (obj_desc), + obj_desc->reference. + class)); + break; + + default: + + ACPI_ERROR((AE_INFO, + "Unknown Reference Class %2.2X in %p", + obj_desc->reference.class, + obj_desc)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + } + break; + + default: + + /* Invalid descriptor */ + + ACPI_ERROR((AE_INFO, "Invalid descriptor %p [%s]", + obj_desc, + acpi_ut_get_descriptor_name(obj_desc))); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* Get one argument type, point to the next */ + + this_arg_type = GET_CURRENT_ARG_TYPE(arg_types); + INCREMENT_ARG_LIST(arg_types); + + /* + * Handle cases where the object does not need to be + * resolved to a value + */ + switch (this_arg_type) { + case ARGI_REF_OR_STRING: /* Can be a String or Reference */ + + if ((ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == + ACPI_DESC_TYPE_OPERAND) + && (ACPI_GET_OBJECT_TYPE(obj_desc) == + ACPI_TYPE_STRING)) { + /* + * String found - the string references a named object and + * must be resolved to a node + */ + goto next_operand; + } + + /* + * Else not a string - fall through to the normal Reference + * case below + */ + /*lint -fallthrough */ + + case ARGI_REFERENCE: /* References: */ + case ARGI_INTEGER_REF: + case ARGI_OBJECT_REF: + case ARGI_DEVICE_REF: + case ARGI_TARGETREF: /* Allows implicit conversion rules before store */ + case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ + case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ + + /* + * Need an operand of type ACPI_TYPE_LOCAL_REFERENCE + * A Namespace Node is OK as-is + */ + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == + ACPI_DESC_TYPE_NAMED) { + goto next_operand; + } + + status = + acpi_ex_check_object_type(ACPI_TYPE_LOCAL_REFERENCE, + object_type, obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + goto next_operand; + + case ARGI_DATAREFOBJ: /* Store operator only */ + + /* + * We don't want to resolve index_op reference objects during + * a store because this would be an implicit de_ref_of operation. + * Instead, we just want to store the reference object. + * -- All others must be resolved below. + */ + if ((opcode == AML_STORE_OP) && + (ACPI_GET_OBJECT_TYPE(*stack_ptr) == + ACPI_TYPE_LOCAL_REFERENCE) + && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) { + goto next_operand; + } + break; + + default: + /* All cases covered above */ + break; + } + + /* + * Resolve this object to a value + */ + status = acpi_ex_resolve_to_value(stack_ptr, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the resolved object */ + + obj_desc = *stack_ptr; + + /* + * Check the resulting object (value) type + */ + switch (this_arg_type) { + /* + * For the simple cases, only one type of resolved object + * is allowed + */ + case ARGI_MUTEX: + + /* Need an operand of type ACPI_TYPE_MUTEX */ + + type_needed = ACPI_TYPE_MUTEX; + break; + + case ARGI_EVENT: + + /* Need an operand of type ACPI_TYPE_EVENT */ + + type_needed = ACPI_TYPE_EVENT; + break; + + case ARGI_PACKAGE: /* Package */ + + /* Need an operand of type ACPI_TYPE_PACKAGE */ + + type_needed = ACPI_TYPE_PACKAGE; + break; + + case ARGI_ANYTYPE: + + /* Any operand type will do */ + + type_needed = ACPI_TYPE_ANY; + break; + + case ARGI_DDBHANDLE: + + /* Need an operand of type ACPI_TYPE_DDB_HANDLE */ + + type_needed = ACPI_TYPE_LOCAL_REFERENCE; + break; + + /* + * The more complex cases allow multiple resolved object types + */ + case ARGI_INTEGER: + + /* + * Need an operand of type ACPI_TYPE_INTEGER, + * But we can implicitly convert from a STRING or BUFFER + * Aka - "Implicit Source Operand Conversion" + */ + status = + acpi_ex_convert_to_integer(obj_desc, stack_ptr, 16); + if (ACPI_FAILURE(status)) { + if (status == AE_TYPE) { + ACPI_ERROR((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + return_ACPI_STATUS(status); + } + + if (obj_desc != *stack_ptr) { + acpi_ut_remove_reference(obj_desc); + } + goto next_operand; + + case ARGI_BUFFER: + + /* + * Need an operand of type ACPI_TYPE_BUFFER, + * But we can implicitly convert from a STRING or INTEGER + * Aka - "Implicit Source Operand Conversion" + */ + status = acpi_ex_convert_to_buffer(obj_desc, stack_ptr); + if (ACPI_FAILURE(status)) { + if (status == AE_TYPE) { + ACPI_ERROR((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + return_ACPI_STATUS(status); + } + + if (obj_desc != *stack_ptr) { + acpi_ut_remove_reference(obj_desc); + } + goto next_operand; + + case ARGI_STRING: + + /* + * Need an operand of type ACPI_TYPE_STRING, + * But we can implicitly convert from a BUFFER or INTEGER + * Aka - "Implicit Source Operand Conversion" + */ + status = acpi_ex_convert_to_string(obj_desc, stack_ptr, + ACPI_IMPLICIT_CONVERT_HEX); + if (ACPI_FAILURE(status)) { + if (status == AE_TYPE) { + ACPI_ERROR((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + return_ACPI_STATUS(status); + } + + if (obj_desc != *stack_ptr) { + acpi_ut_remove_reference(obj_desc); + } + goto next_operand; + + case ARGI_COMPUTEDATA: + + /* Need an operand of type INTEGER, STRING or BUFFER */ + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* Valid operand */ + break; + + default: + ACPI_ERROR((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + goto next_operand; + + case ARGI_BUFFER_OR_STRING: + + /* Need an operand of type STRING or BUFFER */ + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* Valid operand */ + break; + + case ACPI_TYPE_INTEGER: + + /* Highest priority conversion is to type Buffer */ + + status = + acpi_ex_convert_to_buffer(obj_desc, + stack_ptr); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (obj_desc != *stack_ptr) { + acpi_ut_remove_reference(obj_desc); + } + break; + + default: + ACPI_ERROR((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + goto next_operand; + + case ARGI_DATAOBJECT: + /* + * ARGI_DATAOBJECT is only used by the size_of operator. + * Need a buffer, string, package, or ref_of reference. + * + * The only reference allowed here is a direct reference to + * a namespace node. + */ + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_LOCAL_REFERENCE: + + /* Valid operand */ + break; + + default: + ACPI_ERROR((AE_INFO, + "Needed [Buffer/String/Package/Reference], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + goto next_operand; + + case ARGI_COMPLEXOBJ: + + /* Need a buffer or package or (ACPI 2.0) String */ + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* Valid operand */ + break; + + default: + ACPI_ERROR((AE_INFO, + "Needed [Buffer/String/Package], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + goto next_operand; + + case ARGI_REGION_OR_BUFFER: /* Used by Load() only */ + + /* Need an operand of type REGION or a BUFFER (which could be a resolved region field) */ + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_REGION: + + /* Valid operand */ + break; + + default: + ACPI_ERROR((AE_INFO, + "Needed [Region/Buffer], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + goto next_operand; + + case ARGI_DATAREFOBJ: + + /* Used by the Store() operator only */ + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REFERENCE: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + case ACPI_TYPE_DDB_HANDLE: + + /* Valid operand */ + break; + + default: + + if (acpi_gbl_enable_interpreter_slack) { + /* + * Enable original behavior of Store(), allowing any and all + * objects as the source operand. The ACPI spec does not + * allow this, however. + */ + break; + } + + if (target_op == AML_DEBUG_OP) { + + /* Allow store of any object to the Debug object */ + + break; + } + + ACPI_ERROR((AE_INFO, + "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + goto next_operand; + + default: + + /* Unknown type */ + + ACPI_ERROR((AE_INFO, + "Internal - Unknown ARGI (required operand) type %X", + this_arg_type)); + + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Make sure that the original object was resolved to the + * required object type (Simple cases only). + */ + status = acpi_ex_check_object_type(type_needed, + ACPI_GET_OBJECT_TYPE + (*stack_ptr), *stack_ptr); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + next_operand: + /* + * If more operands needed, decrement stack_ptr to point + * to next operand on stack + */ + if (GET_CURRENT_ARG_TYPE(arg_types)) { + stack_ptr--; + } + } + + ACPI_DUMP_OPERANDS(walk_state->operands, + acpi_ps_get_opcode_name(opcode), + walk_state->num_operands); + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c new file mode 100644 index 000000000000..6f5647fdc006 --- /dev/null +++ b/drivers/acpi/acpica/exstore.c @@ -0,0 +1,716 @@ + +/****************************************************************************** + * + * Module Name: exstore - AML Interpreter object store support + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exstore") + +/* Local prototypes */ +static void +acpi_ex_do_debug_object(union acpi_operand_object *source_desc, + u32 level, u32 index); + +static acpi_status +acpi_ex_store_object_to_index(union acpi_operand_object *val_desc, + union acpi_operand_object *dest_desc, + struct acpi_walk_state *walk_state); + +/******************************************************************************* + * + * FUNCTION: acpi_ex_do_debug_object + * + * PARAMETERS: source_desc - Value to be stored + * Level - Indentation level (used for packages) + * Index - Current package element, zero if not pkg + * + * RETURN: None + * + * DESCRIPTION: Handles stores to the Debug Object. + * + ******************************************************************************/ + +static void +acpi_ex_do_debug_object(union acpi_operand_object *source_desc, + u32 level, u32 index) +{ + u32 i; + + ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); + + /* Print line header as long as we are not in the middle of an object display */ + + if (!((level > 0) && index == 0)) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", + level, " ")); + } + + /* Display index for package output only */ + + if (index > 0) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + "(%.2u) ", index - 1)); + } + + if (!source_desc) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Null Object]\n")); + return_VOID; + } + + if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s ", + acpi_ut_get_object_type_name + (source_desc))); + + if (!acpi_ut_valid_internal_object(source_desc)) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + "%p, Invalid Internal Object!\n", + source_desc)); + return_VOID; + } + } else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == + ACPI_DESC_TYPE_NAMED) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: %p\n", + acpi_ut_get_type_name(((struct + acpi_namespace_node + *)source_desc)-> + type), + source_desc)); + return_VOID; + } else { + return_VOID; + } + + /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ + + switch (ACPI_GET_OBJECT_TYPE(source_desc)) { + case ACPI_TYPE_INTEGER: + + /* Output correct integer width */ + + if (acpi_gbl_integer_byte_width == 4) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n", + (u32) source_desc->integer. + value)); + } else { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + "0x%8.8X%8.8X\n", + ACPI_FORMAT_UINT64(source_desc-> + integer. + value))); + } + break; + + case ACPI_TYPE_BUFFER: + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]\n", + (u32) source_desc->buffer.length)); + ACPI_DUMP_BUFFER(source_desc->buffer.pointer, + (source_desc->buffer.length < + 256) ? source_desc->buffer.length : 256); + break; + + case ACPI_TYPE_STRING: + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n", + source_desc->string.length, + source_desc->string.pointer)); + break; + + case ACPI_TYPE_PACKAGE: + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + "[Contains 0x%.2X Elements]\n", + source_desc->package.count)); + + /* Output the entire contents of the package */ + + for (i = 0; i < source_desc->package.count; i++) { + acpi_ex_do_debug_object(source_desc->package. + elements[i], level + 4, i + 1); + } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s] ", + acpi_ut_get_reference_name(source_desc))); + + /* Decode the reference */ + + switch (source_desc->reference.class) { + case ACPI_REFCLASS_INDEX: + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%X\n", + source_desc->reference.value)); + break; + + case ACPI_REFCLASS_TABLE: + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + "Table Index 0x%X\n", + source_desc->reference.value)); + break; + + default: + break; + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " ")); + + /* Check for valid node first, then valid object */ + + if (source_desc->reference.node) { + if (ACPI_GET_DESCRIPTOR_TYPE + (source_desc->reference.node) != + ACPI_DESC_TYPE_NAMED) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + " %p - Not a valid namespace node\n", + source_desc->reference. + node)); + } else { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, + "Node %p [%4.4s] ", + source_desc->reference. + node, + (source_desc->reference. + node)->name.ascii)); + + switch ((source_desc->reference.node)->type) { + + /* These types have no attached object */ + + case ACPI_TYPE_DEVICE: + acpi_os_printf("Device\n"); + break; + + case ACPI_TYPE_THERMAL: + acpi_os_printf("Thermal Zone\n"); + break; + + default: + acpi_ex_do_debug_object((source_desc-> + reference. + node)->object, + level + 4, 0); + break; + } + } + } else if (source_desc->reference.object) { + if (ACPI_GET_DESCRIPTOR_TYPE + (source_desc->reference.object) == + ACPI_DESC_TYPE_NAMED) { + acpi_ex_do_debug_object(((struct + acpi_namespace_node *) + source_desc->reference. + object)->object, + level + 4, 0); + } else { + acpi_ex_do_debug_object(source_desc->reference. + object, level + 4, 0); + } + } + break; + + default: + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p\n", + source_desc)); + break; + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n")); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_store + * + * PARAMETERS: *source_desc - Value to be stored + * *dest_desc - Where to store it. Must be an NS node + * or an union acpi_operand_object of type + * Reference; + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Store the value described by source_desc into the location + * described by dest_desc. Called by various interpreter + * functions to store the result of an operation into + * the destination operand -- not just simply the actual "Store" + * ASL operator. + * + ******************************************************************************/ + +acpi_status +acpi_ex_store(union acpi_operand_object *source_desc, + union acpi_operand_object *dest_desc, + struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_operand_object *ref_desc = dest_desc; + + ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc); + + /* Validate parameters */ + + if (!source_desc || !dest_desc) { + ACPI_ERROR((AE_INFO, "Null parameter")); + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + /* dest_desc can be either a namespace node or an ACPI object */ + + if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) { + /* + * Dest is a namespace node, + * Storing an object into a Named node. + */ + status = acpi_ex_store_object_to_node(source_desc, + (struct + acpi_namespace_node *) + dest_desc, walk_state, + ACPI_IMPLICIT_CONVERSION); + + return_ACPI_STATUS(status); + } + + /* Destination object must be a Reference or a Constant object */ + + switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { + case ACPI_TYPE_LOCAL_REFERENCE: + break; + + case ACPI_TYPE_INTEGER: + + /* Allow stores to Constants -- a Noop as per ACPI spec */ + + if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) { + return_ACPI_STATUS(AE_OK); + } + + /*lint -fallthrough */ + + default: + + /* Destination is not a Reference object */ + + ACPI_ERROR((AE_INFO, + "Target is not a Reference or Constant object - %s [%p]", + acpi_ut_get_object_type_name(dest_desc), + dest_desc)); + + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* + * Examine the Reference class. These cases are handled: + * + * 1) Store to Name (Change the object associated with a name) + * 2) Store to an indexed area of a Buffer or Package + * 3) Store to a Method Local or Arg + * 4) Store to the debug object + */ + switch (ref_desc->reference.class) { + case ACPI_REFCLASS_REFOF: + + /* Storing an object into a Name "container" */ + + status = acpi_ex_store_object_to_node(source_desc, + ref_desc->reference. + object, walk_state, + ACPI_IMPLICIT_CONVERSION); + break; + + case ACPI_REFCLASS_INDEX: + + /* Storing to an Index (pointer into a packager or buffer) */ + + status = + acpi_ex_store_object_to_index(source_desc, ref_desc, + walk_state); + break; + + case ACPI_REFCLASS_LOCAL: + case ACPI_REFCLASS_ARG: + + /* Store to a method local/arg */ + + status = + acpi_ds_store_object_to_local(ref_desc->reference.class, + ref_desc->reference.value, + source_desc, walk_state); + break; + + case ACPI_REFCLASS_DEBUG: + + /* + * Storing to the Debug object causes the value stored to be + * displayed and otherwise has no effect -- see ACPI Specification + */ + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "**** Write to Debug Object: Object %p %s ****:\n\n", + source_desc, + acpi_ut_get_object_type_name(source_desc))); + + acpi_ex_do_debug_object(source_desc, 0, 0); + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X", + ref_desc->reference.class)); + ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO); + + status = AE_AML_INTERNAL; + break; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_store_object_to_index + * + * PARAMETERS: *source_desc - Value to be stored + * *dest_desc - Named object to receive the value + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Store the object to indexed Buffer or Package element + * + ******************************************************************************/ + +static acpi_status +acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, + union acpi_operand_object *index_desc, + struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_operand_object *obj_desc; + union acpi_operand_object *new_desc; + u8 value = 0; + u32 i; + + ACPI_FUNCTION_TRACE(ex_store_object_to_index); + + /* + * Destination must be a reference pointer, and + * must point to either a buffer or a package + */ + switch (index_desc->reference.target_type) { + case ACPI_TYPE_PACKAGE: + /* + * Storing to a package element. Copy the object and replace + * any existing object with the new object. No implicit + * conversion is performed. + * + * The object at *(index_desc->Reference.Where) is the + * element within the package that is to be modified. + * The parent package object is at index_desc->Reference.Object + */ + obj_desc = *(index_desc->reference.where); + + if (ACPI_GET_OBJECT_TYPE(source_desc) == + ACPI_TYPE_LOCAL_REFERENCE + && source_desc->reference.class == ACPI_REFCLASS_TABLE) { + + /* This is a DDBHandle, just add a reference to it */ + + acpi_ut_add_reference(source_desc); + new_desc = source_desc; + } else { + /* Normal object, copy it */ + + status = + acpi_ut_copy_iobject_to_iobject(source_desc, + &new_desc, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + if (obj_desc) { + + /* Decrement reference count by the ref count of the parent package */ + + for (i = 0; i < ((union acpi_operand_object *) + index_desc->reference.object)->common. + reference_count; i++) { + acpi_ut_remove_reference(obj_desc); + } + } + + *(index_desc->reference.where) = new_desc; + + /* Increment ref count by the ref count of the parent package-1 */ + + for (i = 1; i < ((union acpi_operand_object *) + index_desc->reference.object)->common. + reference_count; i++) { + acpi_ut_add_reference(new_desc); + } + + break; + + case ACPI_TYPE_BUFFER_FIELD: + + /* + * Store into a Buffer or String (not actually a real buffer_field) + * at a location defined by an Index. + * + * The first 8-bit element of the source object is written to the + * 8-bit Buffer location defined by the Index destination object, + * according to the ACPI 2.0 specification. + */ + + /* + * Make sure the target is a Buffer or String. An error should + * not happen here, since the reference_object was constructed + * by the INDEX_OP code. + */ + obj_desc = index_desc->reference.object; + if ((ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_BUFFER) && + (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_STRING)) { + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* + * The assignment of the individual elements will be slightly + * different for each source type. + */ + switch (ACPI_GET_OBJECT_TYPE(source_desc)) { + case ACPI_TYPE_INTEGER: + + /* Use the least-significant byte of the integer */ + + value = (u8) (source_desc->integer.value); + break; + + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_STRING: + + /* Note: Takes advantage of common string/buffer fields */ + + value = source_desc->buffer.pointer[0]; + break; + + default: + + /* All other types are invalid */ + + ACPI_ERROR((AE_INFO, + "Source must be Integer/Buffer/String type, not %s", + acpi_ut_get_object_type_name(source_desc))); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* Store the source value into the target buffer byte */ + + obj_desc->buffer.pointer[index_desc->reference.value] = value; + break; + + default: + ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField")); + status = AE_AML_OPERAND_TYPE; + break; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_store_object_to_node + * + * PARAMETERS: source_desc - Value to be stored + * Node - Named object to receive the value + * walk_state - Current walk state + * implicit_conversion - Perform implicit conversion (yes/no) + * + * RETURN: Status + * + * DESCRIPTION: Store the object to the named object. + * + * The Assignment of an object to a named object is handled here + * The value passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * Assumes parameters are already validated. + * + ******************************************************************************/ + +acpi_status +acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, + struct acpi_namespace_node *node, + struct acpi_walk_state *walk_state, + u8 implicit_conversion) +{ + acpi_status status = AE_OK; + union acpi_operand_object *target_desc; + union acpi_operand_object *new_desc; + acpi_object_type target_type; + + ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc); + + /* Get current type of the node, and object attached to Node */ + + target_type = acpi_ns_get_type(node); + target_desc = acpi_ns_get_attached_object(node); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", + source_desc, + acpi_ut_get_object_type_name(source_desc), node, + acpi_ut_get_type_name(target_type))); + + /* + * Resolve the source object to an actual value + * (If it is a reference object) + */ + status = acpi_ex_resolve_object(&source_desc, target_type, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* If no implicit conversion, drop into the default case below */ + + if ((!implicit_conversion) || + ((walk_state->opcode == AML_COPY_OP) && + (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && + (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && + (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { + /* + * Force execution of default (no implicit conversion). Note: + * copy_object does not perform an implicit conversion, as per the ACPI + * spec -- except in case of region/bank/index fields -- because these + * objects must retain their original type permanently. + */ + target_type = ACPI_TYPE_ANY; + } + + /* Do the actual store operation */ + + switch (target_type) { + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + /* For fields, copy the source data to the target field. */ + + status = acpi_ex_write_data_to_field(source_desc, target_desc, + &walk_state->result_obj); + break; + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * These target types are all of type Integer/String/Buffer, and + * therefore support implicit conversion before the store. + * + * Copy and/or convert the source object to a new target object + */ + status = + acpi_ex_store_object_to_object(source_desc, target_desc, + &new_desc, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (new_desc != target_desc) { + /* + * Store the new new_desc as the new value of the Name, and set + * the Name's type to that of the value being stored in it. + * source_desc reference count is incremented by attach_object. + * + * Note: This may change the type of the node if an explicit store + * has been performed such that the node/object type has been + * changed. + */ + status = + acpi_ns_attach_object(node, new_desc, + new_desc->common.type); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Store %s into %s via Convert/Attach\n", + acpi_ut_get_object_type_name + (source_desc), + acpi_ut_get_object_type_name + (new_desc))); + } + break; + + default: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Storing %s (%p) directly into node (%p) with no implicit conversion\n", + acpi_ut_get_object_type_name(source_desc), + source_desc, node)); + + /* No conversions for all other types. Just attach the source object */ + + status = acpi_ns_attach_object(node, source_desc, + ACPI_GET_OBJECT_TYPE + (source_desc)); + break; + } + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c new file mode 100644 index 000000000000..ad2047afa463 --- /dev/null +++ b/drivers/acpi/acpica/exstoren.c @@ -0,0 +1,304 @@ + +/****************************************************************************** + * + * Module Name: exstoren - AML Interpreter object store support, + * Store to Node (namespace object) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exstoren") + +/******************************************************************************* + * + * FUNCTION: acpi_ex_resolve_object + * + * PARAMETERS: source_desc_ptr - Pointer to the source object + * target_type - Current type of the target + * walk_state - Current walk state + * + * RETURN: Status, resolved object in source_desc_ptr. + * + * DESCRIPTION: Resolve an object. If the object is a reference, dereference + * it and return the actual object in the source_desc_ptr. + * + ******************************************************************************/ +acpi_status +acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, + acpi_object_type target_type, + struct acpi_walk_state *walk_state) +{ + union acpi_operand_object *source_desc = *source_desc_ptr; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_resolve_object); + + /* Ensure we have a Target that can be stored to */ + + switch (target_type) { + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + /* + * These cases all require only Integers or values that + * can be converted to Integers (Strings or Buffers) + */ + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * Stores into a Field/Region or into a Integer/Buffer/String + * are all essentially the same. This case handles the + * "interchangeable" types Integer, String, and Buffer. + */ + if (ACPI_GET_OBJECT_TYPE(source_desc) == + ACPI_TYPE_LOCAL_REFERENCE) { + + /* Resolve a reference object first */ + + status = + acpi_ex_resolve_to_value(source_desc_ptr, + walk_state); + if (ACPI_FAILURE(status)) { + break; + } + } + + /* For copy_object, no further validation necessary */ + + if (walk_state->opcode == AML_COPY_OP) { + break; + } + + /* Must have a Integer, Buffer, or String */ + + if ((ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) && + (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) && + (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) && + !((ACPI_GET_OBJECT_TYPE(source_desc) == + ACPI_TYPE_LOCAL_REFERENCE) + && (source_desc->reference.class == + ACPI_REFCLASS_TABLE))) { + + /* Conversion successful but still not a valid type */ + + ACPI_ERROR((AE_INFO, + "Cannot assign type %s to %s (must be type Int/Str/Buf)", + acpi_ut_get_object_type_name(source_desc), + acpi_ut_get_type_name(target_type))); + status = AE_AML_OPERAND_TYPE; + } + break; + + case ACPI_TYPE_LOCAL_ALIAS: + case ACPI_TYPE_LOCAL_METHOD_ALIAS: + + /* + * All aliases should have been resolved earlier, during the + * operand resolution phase. + */ + ACPI_ERROR((AE_INFO, "Store into an unresolved Alias object")); + status = AE_AML_INTERNAL; + break; + + case ACPI_TYPE_PACKAGE: + default: + + /* + * All other types than Alias and the various Fields come here, + * including the untyped case - ACPI_TYPE_ANY. + */ + break; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_store_object_to_object + * + * PARAMETERS: source_desc - Object to store + * dest_desc - Object to receive a copy of the source + * new_desc - New object if dest_desc is obsoleted + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: "Store" an object to another object. This may include + * converting the source type to the target type (implicit + * conversion), and a copy of the value of the source to + * the target. + * + * The Assignment of an object to another (not named) object + * is handled here. + * The Source passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * This module allows destination types of Number, String, + * Buffer, and Package. + * + * Assumes parameters are already validated. NOTE: source_desc + * resolution (from a reference object) must be performed by + * the caller if necessary. + * + ******************************************************************************/ + +acpi_status +acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, + union acpi_operand_object *dest_desc, + union acpi_operand_object **new_desc, + struct acpi_walk_state *walk_state) +{ + union acpi_operand_object *actual_src_desc; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_object, source_desc); + + actual_src_desc = source_desc; + if (!dest_desc) { + /* + * There is no destination object (An uninitialized node or + * package element), so we can simply copy the source object + * creating a new destination object + */ + status = + acpi_ut_copy_iobject_to_iobject(actual_src_desc, new_desc, + walk_state); + return_ACPI_STATUS(status); + } + + if (ACPI_GET_OBJECT_TYPE(source_desc) != + ACPI_GET_OBJECT_TYPE(dest_desc)) { + /* + * The source type does not match the type of the destination. + * Perform the "implicit conversion" of the source to the current type + * of the target as per the ACPI specification. + * + * If no conversion performed, actual_src_desc = source_desc. + * Otherwise, actual_src_desc is a temporary object to hold the + * converted object. + */ + status = + acpi_ex_convert_to_target_type(ACPI_GET_OBJECT_TYPE + (dest_desc), source_desc, + &actual_src_desc, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (source_desc == actual_src_desc) { + /* + * No conversion was performed. Return the source_desc as the + * new object. + */ + *new_desc = source_desc; + return_ACPI_STATUS(AE_OK); + } + } + + /* + * We now have two objects of identical types, and we can perform a + * copy of the *value* of the source object. + */ + switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { + case ACPI_TYPE_INTEGER: + + dest_desc->integer.value = actual_src_desc->integer.value; + + /* Truncate value if we are executing from a 32-bit ACPI table */ + + acpi_ex_truncate_for32bit_table(dest_desc); + break; + + case ACPI_TYPE_STRING: + + status = + acpi_ex_store_string_to_string(actual_src_desc, dest_desc); + break; + + case ACPI_TYPE_BUFFER: + + status = + acpi_ex_store_buffer_to_buffer(actual_src_desc, dest_desc); + break; + + case ACPI_TYPE_PACKAGE: + + status = + acpi_ut_copy_iobject_to_iobject(actual_src_desc, &dest_desc, + walk_state); + break; + + default: + /* + * All other types come here. + */ + ACPI_WARNING((AE_INFO, "Store into type %s not implemented", + acpi_ut_get_object_type_name(dest_desc))); + + status = AE_NOT_IMPLEMENTED; + break; + } + + if (actual_src_desc != source_desc) { + + /* Delete the intermediate (temporary) source object */ + + acpi_ut_remove_reference(actual_src_desc); + } + + *new_desc = dest_desc; + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c new file mode 100644 index 000000000000..a48d580d71c2 --- /dev/null +++ b/drivers/acpi/acpica/exstorob.c @@ -0,0 +1,209 @@ + +/****************************************************************************** + * + * Module Name: exstorob - AML Interpreter object store support, store to object + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exstorob") + +/******************************************************************************* + * + * FUNCTION: acpi_ex_store_buffer_to_buffer + * + * PARAMETERS: source_desc - Source object to copy + * target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Copy a buffer object to another buffer object. + * + ******************************************************************************/ +acpi_status +acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, + union acpi_operand_object *target_desc) +{ + u32 length; + u8 *buffer; + + ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc); + + /* We know that source_desc is a buffer by now */ + + buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer); + length = source_desc->buffer.length; + + /* + * If target is a buffer of length zero or is a static buffer, + * allocate a new buffer of the proper length + */ + if ((target_desc->buffer.length == 0) || + (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) { + target_desc->buffer.pointer = ACPI_ALLOCATE(length); + if (!target_desc->buffer.pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + target_desc->buffer.length = length; + } + + /* Copy source buffer to target buffer */ + + if (length <= target_desc->buffer.length) { + + /* Clear existing buffer and copy in the new one */ + + ACPI_MEMSET(target_desc->buffer.pointer, 0, + target_desc->buffer.length); + ACPI_MEMCPY(target_desc->buffer.pointer, buffer, length); + +#ifdef ACPI_OBSOLETE_BEHAVIOR + /* + * NOTE: ACPI versions up to 3.0 specified that the buffer must be + * truncated if the string is smaller than the buffer. However, "other" + * implementations of ACPI never did this and thus became the defacto + * standard. ACPI 3.0_a changes this behavior such that the buffer + * is no longer truncated. + */ + + /* + * OBSOLETE BEHAVIOR: + * If the original source was a string, we must truncate the buffer, + * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer + * copy must not truncate the original buffer. + */ + if (original_src_type == ACPI_TYPE_STRING) { + + /* Set the new length of the target */ + + target_desc->buffer.length = length; + } +#endif + } else { + /* Truncate the source, copy only what will fit */ + + ACPI_MEMCPY(target_desc->buffer.pointer, buffer, + target_desc->buffer.length); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Truncating source buffer from %X to %X\n", + length, target_desc->buffer.length)); + } + + /* Copy flags */ + + target_desc->buffer.flags = source_desc->buffer.flags; + target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_store_string_to_string + * + * PARAMETERS: source_desc - Source object to copy + * target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Copy a String object to another String object + * + ******************************************************************************/ + +acpi_status +acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, + union acpi_operand_object *target_desc) +{ + u32 length; + u8 *buffer; + + ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc); + + /* We know that source_desc is a string by now */ + + buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer); + length = source_desc->string.length; + + /* + * Replace existing string value if it will fit and the string + * pointer is not a static pointer (part of an ACPI table) + */ + if ((length < target_desc->string.length) && + (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { + /* + * String will fit in existing non-static buffer. + * Clear old string and copy in the new one + */ + ACPI_MEMSET(target_desc->string.pointer, 0, + (acpi_size) target_desc->string.length + 1); + ACPI_MEMCPY(target_desc->string.pointer, buffer, length); + } else { + /* + * Free the current buffer, then allocate a new buffer + * large enough to hold the value + */ + if (target_desc->string.pointer && + (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { + + /* Only free if not a pointer into the DSDT */ + + ACPI_FREE(target_desc->string.pointer); + } + + target_desc->string.pointer = ACPI_ALLOCATE_ZEROED((acpi_size) + length + 1); + if (!target_desc->string.pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; + ACPI_MEMCPY(target_desc->string.pointer, buffer, length); + } + + /* Set the new target length */ + + target_desc->string.length = length; + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c new file mode 100644 index 000000000000..a25b2c576eb1 --- /dev/null +++ b/drivers/acpi/acpica/exsystem.c @@ -0,0 +1,303 @@ + +/****************************************************************************** + * + * Module Name: exsystem - Interface to OS services + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exsystem") + +/******************************************************************************* + * + * FUNCTION: acpi_ex_system_wait_semaphore + * + * PARAMETERS: Semaphore - Semaphore to wait on + * Timeout - Max time to wait + * + * RETURN: Status + * + * DESCRIPTION: Implements a semaphore wait with a check to see if the + * semaphore is available immediately. If it is not, the + * interpreter is released before waiting. + * + ******************************************************************************/ +acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); + + status = acpi_os_wait_semaphore(semaphore, 1, ACPI_DO_NOT_WAIT); + if (ACPI_SUCCESS(status)) { + return_ACPI_STATUS(status); + } + + if (status == AE_TIME) { + + /* We must wait, so unlock the interpreter */ + + acpi_ex_relinquish_interpreter(); + + status = acpi_os_wait_semaphore(semaphore, 1, timeout); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "*** Thread awake after blocking, %s\n", + acpi_format_exception(status))); + + /* Reacquire the interpreter */ + + acpi_ex_reacquire_interpreter(); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_system_wait_mutex + * + * PARAMETERS: Mutex - Mutex to wait on + * Timeout - Max time to wait + * + * RETURN: Status + * + * DESCRIPTION: Implements a mutex wait with a check to see if the + * mutex is available immediately. If it is not, the + * interpreter is released before waiting. + * + ******************************************************************************/ + +acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ex_system_wait_mutex); + + status = acpi_os_acquire_mutex(mutex, ACPI_DO_NOT_WAIT); + if (ACPI_SUCCESS(status)) { + return_ACPI_STATUS(status); + } + + if (status == AE_TIME) { + + /* We must wait, so unlock the interpreter */ + + acpi_ex_relinquish_interpreter(); + + status = acpi_os_acquire_mutex(mutex, timeout); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "*** Thread awake after blocking, %s\n", + acpi_format_exception(status))); + + /* Reacquire the interpreter */ + + acpi_ex_reacquire_interpreter(); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_system_do_stall + * + * PARAMETERS: how_long - The amount of time to stall, + * in microseconds + * + * RETURN: Status + * + * DESCRIPTION: Suspend running thread for specified amount of time. + * Note: ACPI specification requires that Stall() does not + * relinquish the processor, and delays longer than 100 usec + * should use Sleep() instead. We allow stalls up to 255 usec + * for compatibility with other interpreters and existing BIOSs. + * + ******************************************************************************/ + +acpi_status acpi_ex_system_do_stall(u32 how_long) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_ENTRY(); + + if (how_long > 255) { /* 255 microseconds */ + /* + * Longer than 255 usec, this is an error + * + * (ACPI specifies 100 usec as max, but this gives some slack in + * order to support existing BIOSs) + */ + ACPI_ERROR((AE_INFO, "Time parameter is too large (%d)", + how_long)); + status = AE_AML_OPERAND_VALUE; + } else { + acpi_os_stall(how_long); + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_system_do_suspend + * + * PARAMETERS: how_long - The amount of time to suspend, + * in milliseconds + * + * RETURN: None + * + * DESCRIPTION: Suspend running thread for specified amount of time. + * + ******************************************************************************/ + +acpi_status acpi_ex_system_do_suspend(acpi_integer how_long) +{ + ACPI_FUNCTION_ENTRY(); + + /* Since this thread will sleep, we must release the interpreter */ + + acpi_ex_relinquish_interpreter(); + + acpi_os_sleep(how_long); + + /* And now we must get the interpreter again */ + + acpi_ex_reacquire_interpreter(); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_system_signal_event + * + * PARAMETERS: obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. + * + ******************************************************************************/ + +acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_system_signal_event); + + if (obj_desc) { + status = + acpi_os_signal_semaphore(obj_desc->event.os_semaphore, 1); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_system_wait_event + * + * PARAMETERS: time_desc - The 'time to delay' object descriptor + * obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This operation is a request to wait for an + * event. + * + ******************************************************************************/ + +acpi_status +acpi_ex_system_wait_event(union acpi_operand_object *time_desc, + union acpi_operand_object *obj_desc) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_system_wait_event); + + if (obj_desc) { + status = + acpi_ex_system_wait_semaphore(obj_desc->event.os_semaphore, + (u16) time_desc->integer. + value); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_system_reset_event + * + * PARAMETERS: obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Reset an event to a known state. + * + ******************************************************************************/ + +acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc) +{ + acpi_status status = AE_OK; + acpi_semaphore temp_semaphore; + + ACPI_FUNCTION_ENTRY(); + + /* + * We are going to simply delete the existing semaphore and + * create a new one! + */ + status = + acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore); + if (ACPI_SUCCESS(status)) { + (void)acpi_os_delete_semaphore(obj_desc->event.os_semaphore); + obj_desc->event.os_semaphore = temp_semaphore; + } + + return (status); +} diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c new file mode 100644 index 000000000000..0ecdb70c4980 --- /dev/null +++ b/drivers/acpi/acpica/exutils.c @@ -0,0 +1,421 @@ + +/****************************************************************************** + * + * Module Name: exutils - interpreter/scanner utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * DEFINE_AML_GLOBALS is tested in amlcode.h + * to determine whether certain global names should be "defined" or only + * "declared" in the current compilation. This enhances maintainability + * by enabling a single header file to embody all knowledge of the names + * in question. + * + * Exactly one module of any executable should #define DEFINE_GLOBALS + * before #including the header files which use this convention. The + * names in question will be defined and initialized in that module, + * and declared as extern in all other modules which #include those + * header files. + */ + +#define DEFINE_AML_GLOBALS + +#include +#include +#include +#include + +#define _COMPONENT ACPI_EXECUTER +ACPI_MODULE_NAME("exutils") + +/* Local prototypes */ +static u32 acpi_ex_digits_needed(acpi_integer value, u32 base); + +#ifndef ACPI_NO_METHOD_EXECUTION +/******************************************************************************* + * + * FUNCTION: acpi_ex_enter_interpreter + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Enter the interpreter execution region. Failure to enter + * the interpreter region is a fatal system error. Used in + * conjunction with exit_interpreter. + * + ******************************************************************************/ + +void acpi_ex_enter_interpreter(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ex_enter_interpreter); + + status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not acquire AML Interpreter mutex")); + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_reacquire_interpreter + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Reacquire the interpreter execution region from within the + * interpreter code. Failure to enter the interpreter region is a + * fatal system error. Used in conjuction with + * relinquish_interpreter + * + ******************************************************************************/ + +void acpi_ex_reacquire_interpreter(void) +{ + ACPI_FUNCTION_TRACE(ex_reacquire_interpreter); + + /* + * If the global serialized flag is set, do not release the interpreter, + * since it was not actually released by acpi_ex_relinquish_interpreter. + * This forces the interpreter to be single threaded. + */ + if (!acpi_gbl_all_methods_serialized) { + acpi_ex_enter_interpreter(); + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_exit_interpreter + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Exit the interpreter execution region. This is the top level + * routine used to exit the interpreter when all processing has + * been completed. + * + ******************************************************************************/ + +void acpi_ex_exit_interpreter(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ex_exit_interpreter); + + status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not release AML Interpreter mutex")); + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_relinquish_interpreter + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Exit the interpreter execution region, from within the + * interpreter - before attempting an operation that will possibly + * block the running thread. + * + * Cases where the interpreter is unlocked internally + * 1) Method to be blocked on a Sleep() AML opcode + * 2) Method to be blocked on an Acquire() AML opcode + * 3) Method to be blocked on a Wait() AML opcode + * 4) Method to be blocked to acquire the global lock + * 5) Method to be blocked waiting to execute a serialized control method + * that is currently executing + * 6) About to invoke a user-installed opregion handler + * + ******************************************************************************/ + +void acpi_ex_relinquish_interpreter(void) +{ + ACPI_FUNCTION_TRACE(ex_relinquish_interpreter); + + /* + * If the global serialized flag is set, do not release the interpreter. + * This forces the interpreter to be single threaded. + */ + if (!acpi_gbl_all_methods_serialized) { + acpi_ex_exit_interpreter(); + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_truncate_for32bit_table + * + * PARAMETERS: obj_desc - Object to be truncated + * + * RETURN: none + * + * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is + * 32-bit, as determined by the revision of the DSDT. + * + ******************************************************************************/ + +void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) +{ + + ACPI_FUNCTION_ENTRY(); + + /* + * Object must be a valid number and we must be executing + * a control method. NS node could be there for AML_INT_NAMEPATH_OP. + */ + if ((!obj_desc) || + (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) || + (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { + return; + } + + if (acpi_gbl_integer_byte_width == 4) { + /* + * We are running a method that exists in a 32-bit ACPI table. + * Truncate the value to 32 bits by zeroing out the upper 32-bit field + */ + obj_desc->integer.value &= (acpi_integer) ACPI_UINT32_MAX; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_acquire_global_lock + * + * PARAMETERS: field_flags - Flags with Lock rule: + * always_lock or never_lock + * + * RETURN: None + * + * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field + * flags specifiy that it is to be obtained before field access. + * + ******************************************************************************/ + +void acpi_ex_acquire_global_lock(u32 field_flags) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ex_acquire_global_lock); + + /* Only use the lock if the always_lock bit is set */ + + if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { + return_VOID; + } + + /* Attempt to get the global lock, wait forever */ + + status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER, + acpi_gbl_global_lock_mutex, + acpi_os_get_thread_id()); + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not acquire Global Lock")); + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_release_global_lock + * + * PARAMETERS: field_flags - Flags with Lock rule: + * always_lock or never_lock + * + * RETURN: None + * + * DESCRIPTION: Release the ACPI hardware Global Lock + * + ******************************************************************************/ + +void acpi_ex_release_global_lock(u32 field_flags) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ex_release_global_lock); + + /* Only use the lock if the always_lock bit is set */ + + if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { + return_VOID; + } + + /* Release the global lock */ + + status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); + if (ACPI_FAILURE(status)) { + + /* Report the error, but there isn't much else we can do */ + + ACPI_EXCEPTION((AE_INFO, status, + "Could not release Global Lock")); + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_digits_needed + * + * PARAMETERS: Value - Value to be represented + * Base - Base of representation + * + * RETURN: The number of digits. + * + * DESCRIPTION: Calculate the number of digits needed to represent the Value + * in the given Base (Radix) + * + ******************************************************************************/ + +static u32 acpi_ex_digits_needed(acpi_integer value, u32 base) +{ + u32 num_digits; + acpi_integer current_value; + + ACPI_FUNCTION_TRACE(ex_digits_needed); + + /* acpi_integer is unsigned, so we don't worry about a '-' prefix */ + + if (value == 0) { + return_UINT32(1); + } + + current_value = value; + num_digits = 0; + + /* Count the digits in the requested base */ + + while (current_value) { + (void)acpi_ut_short_divide(current_value, base, ¤t_value, + NULL); + num_digits++; + } + + return_UINT32(num_digits); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_eisa_id_to_string + * + * PARAMETERS: numeric_id - EISA ID to be converted + * out_string - Where to put the converted string (8 bytes) + * + * RETURN: None + * + * DESCRIPTION: Convert a numeric EISA ID to string representation + * + ******************************************************************************/ + +void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string) +{ + u32 eisa_id; + + ACPI_FUNCTION_ENTRY(); + + /* Swap ID to big-endian to get contiguous bits */ + + eisa_id = acpi_ut_dword_byte_swap(numeric_id); + + out_string[0] = (char)('@' + (((unsigned long)eisa_id >> 26) & 0x1f)); + out_string[1] = (char)('@' + ((eisa_id >> 21) & 0x1f)); + out_string[2] = (char)('@' + ((eisa_id >> 16) & 0x1f)); + out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 12); + out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 8); + out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 4); + out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 0); + out_string[7] = 0; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_unsigned_integer_to_string + * + * PARAMETERS: Value - Value to be converted + * out_string - Where to put the converted string (8 bytes) + * + * RETURN: None, string + * + * DESCRIPTION: Convert a number to string representation. Assumes string + * buffer is large enough to hold the string. + * + ******************************************************************************/ + +void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string) +{ + u32 count; + u32 digits_needed; + u32 remainder; + + ACPI_FUNCTION_ENTRY(); + + digits_needed = acpi_ex_digits_needed(value, 10); + out_string[digits_needed] = 0; + + for (count = digits_needed; count > 0; count--) { + (void)acpi_ut_short_divide(value, 10, &value, &remainder); + out_string[count - 1] = (char)('0' + remainder); + } +} + +#endif diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c new file mode 100644 index 000000000000..c76e3cd7e749 --- /dev/null +++ b/drivers/acpi/acpica/hwacpi.c @@ -0,0 +1,185 @@ + +/****************************************************************************** + * + * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_HARDWARE +ACPI_MODULE_NAME("hwacpi") + +/****************************************************************************** + * + * FUNCTION: acpi_hw_set_mode + * + * PARAMETERS: Mode - SYS_MODE_ACPI or SYS_MODE_LEGACY + * + * RETURN: Status + * + * DESCRIPTION: Transitions the system into the requested mode. + * + ******************************************************************************/ +acpi_status acpi_hw_set_mode(u32 mode) +{ + + acpi_status status; + u32 retry; + + ACPI_FUNCTION_TRACE(hw_set_mode); + + /* + * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, + * system does not support mode transition. + */ + if (!acpi_gbl_FADT.smi_command) { + ACPI_ERROR((AE_INFO, + "No SMI_CMD in FADT, mode transition failed")); + return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); + } + + /* + * ACPI 2.0 clarified the meaning of ACPI_ENABLE and ACPI_DISABLE + * in FADT: If it is zero, enabling or disabling is not supported. + * As old systems may have used zero for mode transition, + * we make sure both the numbers are zero to determine these + * transitions are not supported. + */ + if (!acpi_gbl_FADT.acpi_enable && !acpi_gbl_FADT.acpi_disable) { + ACPI_ERROR((AE_INFO, + "No ACPI mode transition supported in this system (enable/disable both zero)")); + return_ACPI_STATUS(AE_OK); + } + + switch (mode) { + case ACPI_SYS_MODE_ACPI: + + /* BIOS should have disabled ALL fixed and GP events */ + + status = acpi_os_write_port(acpi_gbl_FADT.smi_command, + (u32) acpi_gbl_FADT.acpi_enable, 8); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Attempting to enable ACPI mode\n")); + break; + + case ACPI_SYS_MODE_LEGACY: + + /* + * BIOS should clear all fixed status bits and restore fixed event + * enable bits to default + */ + status = acpi_os_write_port(acpi_gbl_FADT.smi_command, + (u32) acpi_gbl_FADT.acpi_disable, + 8); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Attempting to enable Legacy (non-ACPI) mode\n")); + break; + + default: + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not write ACPI mode change")); + return_ACPI_STATUS(status); + } + + /* + * Some hardware takes a LONG time to switch modes. Give them 3 sec to + * do so, but allow faster systems to proceed more quickly. + */ + retry = 3000; + while (retry) { + if (acpi_hw_get_mode() == mode) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Mode %X successfully enabled\n", + mode)); + return_ACPI_STATUS(AE_OK); + } + acpi_os_stall(1000); + retry--; + } + + ACPI_ERROR((AE_INFO, "Hardware did not change modes")); + return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_hw_get_mode + * + * PARAMETERS: none + * + * RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY + * + * DESCRIPTION: Return current operating state of system. Determined by + * querying the SCI_EN bit. + * + ******************************************************************************/ + +u32 acpi_hw_get_mode(void) +{ + acpi_status status; + u32 value; + + ACPI_FUNCTION_TRACE(hw_get_mode); + + /* + * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, + * system does not support mode transition. + */ + if (!acpi_gbl_FADT.smi_command) { + return_UINT32(ACPI_SYS_MODE_ACPI); + } + + status = acpi_get_register(ACPI_BITREG_SCI_ENABLE, &value); + if (ACPI_FAILURE(status)) { + return_UINT32(ACPI_SYS_MODE_LEGACY); + } + + if (value) { + return_UINT32(ACPI_SYS_MODE_ACPI); + } else { + return_UINT32(ACPI_SYS_MODE_LEGACY); + } +} diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c new file mode 100644 index 000000000000..2b4a85a839d1 --- /dev/null +++ b/drivers/acpi/acpica/hwgpe.c @@ -0,0 +1,469 @@ + +/****************************************************************************** + * + * Module Name: hwgpe - Low level GPE enable/disable/clear functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_HARDWARE +ACPI_MODULE_NAME("hwgpe") + +/* Local prototypes */ +static acpi_status +acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, + void *context); + +/****************************************************************************** + * + * FUNCTION: acpi_hw_low_disable_gpe + * + * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled + * + * RETURN: Status + * + * DESCRIPTION: Disable a single GPE in the enable register. + * + ******************************************************************************/ + +acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) +{ + struct acpi_gpe_register_info *gpe_register_info; + acpi_status status; + u32 enable_mask; + + /* Get the info block for the entire GPE register */ + + gpe_register_info = gpe_event_info->register_info; + if (!gpe_register_info) { + return (AE_NOT_EXIST); + } + + /* Get current value of the enable register that contains this GPE */ + + status = acpi_read(&enable_mask, &gpe_register_info->enable_address); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Clear just the bit that corresponds to this GPE */ + + ACPI_CLEAR_BIT(enable_mask, + ((u32) 1 << + (gpe_event_info->gpe_number - + gpe_register_info->base_gpe_number))); + + /* Write the updated enable mask */ + + status = acpi_write(enable_mask, &gpe_register_info->enable_address); + return (status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_write_gpe_enable_reg + * + * PARAMETERS: gpe_event_info - Info block for the GPE to be enabled + * + * RETURN: Status + * + * DESCRIPTION: Write a GPE enable register. Note: The bit for this GPE must + * already be cleared or set in the parent register + * enable_for_run mask. + * + ******************************************************************************/ + +acpi_status +acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info) +{ + struct acpi_gpe_register_info *gpe_register_info; + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + /* Get the info block for the entire GPE register */ + + gpe_register_info = gpe_event_info->register_info; + if (!gpe_register_info) { + return (AE_NOT_EXIST); + } + + /* Write the entire GPE (runtime) enable register */ + + status = acpi_write(gpe_register_info->enable_for_run, + &gpe_register_info->enable_address); + + return (status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_clear_gpe + * + * PARAMETERS: gpe_event_info - Info block for the GPE to be cleared + * + * RETURN: Status + * + * DESCRIPTION: Clear the status bit for a single GPE. + * + ******************************************************************************/ + +acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) +{ + acpi_status status; + u8 register_bit; + + ACPI_FUNCTION_ENTRY(); + + register_bit = (u8) + (1 << + (gpe_event_info->gpe_number - + gpe_event_info->register_info->base_gpe_number)); + + /* + * Write a one to the appropriate bit in the status register to + * clear this GPE. + */ + status = acpi_write(register_bit, + &gpe_event_info->register_info->status_address); + + return (status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_get_gpe_status + * + * PARAMETERS: gpe_event_info - Info block for the GPE to queried + * event_status - Where the GPE status is returned + * + * RETURN: Status + * + * DESCRIPTION: Return the status of a single GPE. + * + ******************************************************************************/ + +acpi_status +acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, + acpi_event_status * event_status) +{ + u32 in_byte; + u8 register_bit; + struct acpi_gpe_register_info *gpe_register_info; + acpi_status status; + acpi_event_status local_event_status = 0; + + ACPI_FUNCTION_ENTRY(); + + if (!event_status) { + return (AE_BAD_PARAMETER); + } + + /* Get the info block for the entire GPE register */ + + gpe_register_info = gpe_event_info->register_info; + + /* Get the register bitmask for this GPE */ + + register_bit = (u8) + (1 << + (gpe_event_info->gpe_number - + gpe_event_info->register_info->base_gpe_number)); + + /* GPE currently enabled? (enabled for runtime?) */ + + if (register_bit & gpe_register_info->enable_for_run) { + local_event_status |= ACPI_EVENT_FLAG_ENABLED; + } + + /* GPE enabled for wake? */ + + if (register_bit & gpe_register_info->enable_for_wake) { + local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED; + } + + /* GPE currently active (status bit == 1)? */ + + status = acpi_read(&in_byte, &gpe_register_info->status_address); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + if (register_bit & in_byte) { + local_event_status |= ACPI_EVENT_FLAG_SET; + } + + /* Set return value */ + + (*event_status) = local_event_status; + + unlock_and_exit: + return (status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_disable_gpe_block + * + * PARAMETERS: gpe_xrupt_info - GPE Interrupt info + * gpe_block - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Disable all GPEs within a single GPE block + * + ******************************************************************************/ + +acpi_status +acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, void *context) +{ + u32 i; + acpi_status status; + + /* Examine each GPE Register within the block */ + + for (i = 0; i < gpe_block->register_count; i++) { + + /* Disable all GPEs in this register */ + + status = + acpi_write(0x00, + &gpe_block->register_info[i].enable_address); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_clear_gpe_block + * + * PARAMETERS: gpe_xrupt_info - GPE Interrupt info + * gpe_block - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Clear status bits for all GPEs within a single GPE block + * + ******************************************************************************/ + +acpi_status +acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, void *context) +{ + u32 i; + acpi_status status; + + /* Examine each GPE Register within the block */ + + for (i = 0; i < gpe_block->register_count; i++) { + + /* Clear status on all GPEs in this register */ + + status = + acpi_write(0xFF, + &gpe_block->register_info[i].status_address); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_enable_runtime_gpe_block + * + * PARAMETERS: gpe_xrupt_info - GPE Interrupt info + * gpe_block - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes + * combination wake/run GPEs. + * + ******************************************************************************/ + +acpi_status +acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, void *context) +{ + u32 i; + acpi_status status; + + /* NOTE: assumes that all GPEs are currently disabled */ + + /* Examine each GPE Register within the block */ + + for (i = 0; i < gpe_block->register_count; i++) { + if (!gpe_block->register_info[i].enable_for_run) { + continue; + } + + /* Enable all "runtime" GPEs in this register */ + + status = acpi_write(gpe_block->register_info[i].enable_for_run, + &gpe_block->register_info[i]. + enable_address); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_enable_wakeup_gpe_block + * + * PARAMETERS: gpe_xrupt_info - GPE Interrupt info + * gpe_block - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes + * combination wake/run GPEs. + * + ******************************************************************************/ + +static acpi_status +acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, + void *context) +{ + u32 i; + acpi_status status; + + /* Examine each GPE Register within the block */ + + for (i = 0; i < gpe_block->register_count; i++) { + if (!gpe_block->register_info[i].enable_for_wake) { + continue; + } + + /* Enable all "wake" GPEs in this register */ + + status = acpi_write(gpe_block->register_info[i].enable_for_wake, + &gpe_block->register_info[i]. + enable_address); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_disable_all_gpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Disable and clear all GPEs in all GPE blocks + * + ******************************************************************************/ + +acpi_status acpi_hw_disable_all_gpes(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(hw_disable_all_gpes); + + status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); + status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL); + return_ACPI_STATUS(status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_enable_all_runtime_gpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks + * + ******************************************************************************/ + +acpi_status acpi_hw_enable_all_runtime_gpes(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes); + + status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL); + return_ACPI_STATUS(status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_enable_all_wakeup_gpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks + * + ******************************************************************************/ + +acpi_status acpi_hw_enable_all_wakeup_gpes(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes); + + status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL); + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c new file mode 100644 index 000000000000..4bc3bbba6e9c --- /dev/null +++ b/drivers/acpi/acpica/hwregs.c @@ -0,0 +1,353 @@ + +/******************************************************************************* + * + * Module Name: hwregs - Read/write access functions for the various ACPI + * control and status registers. + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_HARDWARE +ACPI_MODULE_NAME("hwregs") + +/******************************************************************************* + * + * FUNCTION: acpi_hw_clear_acpi_status + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Clears all fixed and general purpose status bits + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ +acpi_status acpi_hw_clear_acpi_status(void) +{ + acpi_status status; + acpi_cpu_flags lock_flags = 0; + + ACPI_FUNCTION_TRACE(hw_clear_acpi_status); + + ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n", + ACPI_BITMASK_ALL_FIXED_STATUS, + (u16) acpi_gbl_FADT.xpm1a_event_block.address)); + + lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); + + status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, + ACPI_BITMASK_ALL_FIXED_STATUS); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* Clear the fixed events */ + + if (acpi_gbl_FADT.xpm1b_event_block.address) { + status = acpi_write(ACPI_BITMASK_ALL_FIXED_STATUS, + &acpi_gbl_FADT.xpm1b_event_block); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + } + + /* Clear the GPE Bits in all GPE registers in all GPE blocks */ + + status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL); + + unlock_and_exit: + acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_hw_get_register_bit_mask + * + * PARAMETERS: register_id - Index of ACPI Register to access + * + * RETURN: The bitmask to be used when accessing the register + * + * DESCRIPTION: Map register_id into a register bitmask. + * + ******************************************************************************/ + +struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) +{ + ACPI_FUNCTION_ENTRY(); + + if (register_id > ACPI_BITREG_MAX) { + ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X", + register_id)); + return (NULL); + } + + return (&acpi_gbl_bit_register_info[register_id]); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_register_read + * + * PARAMETERS: register_id - ACPI Register ID + * return_value - Where the register value is returned + * + * RETURN: Status and the value read. + * + * DESCRIPTION: Read from the specified ACPI register + * + ******************************************************************************/ +acpi_status +acpi_hw_register_read(u32 register_id, u32 * return_value) +{ + u32 value1 = 0; + u32 value2 = 0; + acpi_status status; + + ACPI_FUNCTION_TRACE(hw_register_read); + + switch (register_id) { + case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ + + status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_event_block); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* PM1B is optional */ + + status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_event_block); + value1 |= value2; + break; + + case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ + + status = acpi_read(&value1, &acpi_gbl_xpm1a_enable); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* PM1B is optional */ + + status = acpi_read(&value2, &acpi_gbl_xpm1b_enable); + value1 |= value2; + break; + + case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ + + status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_control_block); + if (ACPI_FAILURE(status)) { + goto exit; + } + + status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_control_block); + value1 |= value2; + break; + + case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ + + status = acpi_read(&value1, &acpi_gbl_FADT.xpm2_control_block); + break; + + case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ + + status = acpi_read(&value1, &acpi_gbl_FADT.xpm_timer_block); + break; + + case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ + + status = + acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8); + break; + + default: + ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id)); + status = AE_BAD_PARAMETER; + break; + } + + exit: + + if (ACPI_SUCCESS(status)) { + *return_value = value1; + } + + return_ACPI_STATUS(status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_register_write + * + * PARAMETERS: register_id - ACPI Register ID + * Value - The value to write + * + * RETURN: Status + * + * DESCRIPTION: Write to the specified ACPI register + * + * NOTE: In accordance with the ACPI specification, this function automatically + * preserves the value of the following bits, meaning that these bits cannot be + * changed via this interface: + * + * PM1_CONTROL[0] = SCI_EN + * PM1_CONTROL[9] + * PM1_STATUS[11] + * + * ACPI References: + * 1) Hardware Ignored Bits: When software writes to a register with ignored + * bit fields, it preserves the ignored bit fields + * 2) SCI_EN: OSPM always preserves this bit position + * + ******************************************************************************/ + +acpi_status acpi_hw_register_write(u32 register_id, u32 value) +{ + acpi_status status; + u32 read_value; + + ACPI_FUNCTION_TRACE(hw_register_write); + + switch (register_id) { + case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ + + /* Perform a read first to preserve certain bits (per ACPI spec) */ + + status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, + &read_value); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Insert the bits to be preserved */ + + ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS, + read_value); + + /* Now we can write the data */ + + status = acpi_write(value, &acpi_gbl_FADT.xpm1a_event_block); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* PM1B is optional */ + + status = acpi_write(value, &acpi_gbl_FADT.xpm1b_event_block); + break; + + case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ + + status = acpi_write(value, &acpi_gbl_xpm1a_enable); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* PM1B is optional */ + + status = acpi_write(value, &acpi_gbl_xpm1b_enable); + break; + + case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ + + /* + * Perform a read first to preserve certain bits (per ACPI spec) + */ + status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, + &read_value); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Insert the bits to be preserved */ + + ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS, + read_value); + + /* Now we can write the data */ + + status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block); + if (ACPI_FAILURE(status)) { + goto exit; + } + + status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block); + break; + + case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ + + status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block); + break; + + case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ + + status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block); + break; + + case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ + + status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block); + break; + + case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ + + status = acpi_write(value, &acpi_gbl_FADT.xpm_timer_block); + break; + + case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ + + /* SMI_CMD is currently always in IO space */ + + status = + acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8); + break; + + default: + status = AE_BAD_PARAMETER; + break; + } + + exit: + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c new file mode 100644 index 000000000000..54dd3ee0760c --- /dev/null +++ b/drivers/acpi/acpica/hwsleep.c @@ -0,0 +1,629 @@ + +/****************************************************************************** + * + * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_HARDWARE +ACPI_MODULE_NAME("hwsleep") + +/******************************************************************************* + * + * FUNCTION: acpi_set_firmware_waking_vector + * + * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode + * entry point. + * + * RETURN: Status + * + * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS + * + ******************************************************************************/ +acpi_status +acpi_set_firmware_waking_vector(u32 physical_address) +{ + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); + + + /* + * According to the ACPI specification 2.0c and later, the 64-bit + * waking vector should be cleared and the 32-bit waking vector should + * be used, unless we want the wake-up code to be called by the BIOS in + * Protected Mode. Some systems (for example HP dv5-1004nr) are known + * to fail to resume if the 64-bit vector is used. + */ + + /* Set the 32-bit vector */ + + acpi_gbl_FACS->firmware_waking_vector = physical_address; + + /* Clear the 64-bit vector if it exists */ + + if ((acpi_gbl_FACS->length > 32) && (acpi_gbl_FACS->version >= 1)) { + acpi_gbl_FACS->xfirmware_waking_vector = 0; + } + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) + +/******************************************************************************* + * + * FUNCTION: acpi_set_firmware_waking_vector64 + * + * PARAMETERS: physical_address - 64-bit physical address of ACPI protected + * mode entry point. + * + * RETURN: Status + * + * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if + * it exists in the table. + * + ******************************************************************************/ +acpi_status +acpi_set_firmware_waking_vector64(u64 physical_address) +{ + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64); + + + /* Determine if the 64-bit vector actually exists */ + + if ((acpi_gbl_FACS->length <= 32) || (acpi_gbl_FACS->version < 1)) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Clear 32-bit vector, set the 64-bit X_ vector */ + + acpi_gbl_FACS->firmware_waking_vector = 0; + acpi_gbl_FACS->xfirmware_waking_vector = physical_address; + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) + +/******************************************************************************* + * + * FUNCTION: acpi_enter_sleep_state_prep + * + * PARAMETERS: sleep_state - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231) + * This function must execute with interrupts enabled. + * We break sleeping into 2 stages so that OSPM can handle + * various OS-specific tasks between the two steps. + * + ******************************************************************************/ +acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) +{ + acpi_status status; + struct acpi_object_list arg_list; + union acpi_object arg; + + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); + + /* + * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. + */ + status = acpi_get_sleep_type_data(sleep_state, + &acpi_gbl_sleep_type_a, + &acpi_gbl_sleep_type_b); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Setup parameter object */ + + arg_list.count = 1; + arg_list.pointer = &arg; + + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; + + /* Run the _PTS method */ + + status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + return_ACPI_STATUS(status); + } + + /* Setup the argument to _SST */ + + switch (sleep_state) { + case ACPI_STATE_S0: + arg.integer.value = ACPI_SST_WORKING; + break; + + case ACPI_STATE_S1: + case ACPI_STATE_S2: + case ACPI_STATE_S3: + arg.integer.value = ACPI_SST_SLEEPING; + break; + + case ACPI_STATE_S4: + arg.integer.value = ACPI_SST_SLEEP_CONTEXT; + break; + + default: + arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is off */ + break; + } + + /* + * Set the system indicators to show the desired sleep state. + * _SST is an optional method (return no error if not found) + */ + status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, + "While executing method _SST")); + } + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) + +/******************************************************************************* + * + * FUNCTION: acpi_enter_sleep_state + * + * PARAMETERS: sleep_state - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ +acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) +{ + u32 PM1Acontrol; + u32 PM1Bcontrol; + struct acpi_bit_register_info *sleep_type_reg_info; + struct acpi_bit_register_info *sleep_enable_reg_info; + u32 in_value; + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); + + if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || + (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { + ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X", + acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); + return_ACPI_STATUS(AE_AML_OPERAND_VALUE); + } + + sleep_type_reg_info = + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); + sleep_enable_reg_info = + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); + + /* Clear wake status */ + + status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Clear all fixed and general purpose status bits */ + + status = acpi_hw_clear_acpi_status(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * 1) Disable/Clear all GPEs + * 2) Enable all wakeup GPEs + */ + status = acpi_hw_disable_all_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + acpi_gbl_system_awake_and_running = FALSE; + + status = acpi_hw_enable_all_wakeup_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Execute the _GTS method */ + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; + + status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + return_ACPI_STATUS(status); + } + + /* Get current value of PM1A control */ + + status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + ACPI_DEBUG_PRINT((ACPI_DB_INIT, + "Entering sleep state [S%d]\n", sleep_state)); + + /* Clear SLP_EN and SLP_TYP fields */ + + PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | + sleep_enable_reg_info->access_bit_mask); + PM1Bcontrol = PM1Acontrol; + + /* Insert SLP_TYP bits */ + + PM1Acontrol |= + (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); + PM1Bcontrol |= + (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); + + /* + * We split the writes of SLP_TYP and SLP_EN to workaround + * poorly implemented hardware. + */ + + /* Write #1: fill in SLP_TYP data */ + + status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, + PM1Acontrol); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, + PM1Bcontrol); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Insert SLP_ENABLE bit */ + + PM1Acontrol |= sleep_enable_reg_info->access_bit_mask; + PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask; + + /* Write #2: SLP_TYP + SLP_EN */ + + ACPI_FLUSH_CPU_CACHE(); + + status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, + PM1Acontrol); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, + PM1Bcontrol); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (sleep_state > ACPI_STATE_S3) { + /* + * We wanted to sleep > S3, but it didn't happen (by virtue of the + * fact that we are still executing!) + * + * Wait ten seconds, then try again. This is to get S4/S5 to work on + * all machines. + * + * We wait so long to allow chipsets that poll this reg very slowly to + * still read the right value. Ideally, this block would go + * away entirely. + */ + acpi_os_stall(10000000); + + status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, + sleep_enable_reg_info-> + access_bit_mask); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* Wait until we enter sleep state */ + + do { + status = acpi_get_register_unlocked(ACPI_BITREG_WAKE_STATUS, + &in_value); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Spin until we wake */ + + } while (!in_value); + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) + +/******************************************************************************* + * + * FUNCTION: acpi_enter_sleep_state_s4bios + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Perform a S4 bios request. + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ +acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) +{ + u32 in_value; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); + + status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_hw_clear_acpi_status(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * 1) Disable/Clear all GPEs + * 2) Enable all wakeup GPEs + */ + status = acpi_hw_disable_all_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + acpi_gbl_system_awake_and_running = FALSE; + + status = acpi_hw_enable_all_wakeup_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_FLUSH_CPU_CACHE(); + + status = acpi_os_write_port(acpi_gbl_FADT.smi_command, + (u32) acpi_gbl_FADT.S4bios_request, 8); + + do { + acpi_os_stall(1000); + status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } while (!in_value); + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) + +/******************************************************************************* + * + * FUNCTION: acpi_leave_sleep_state_prep + * + * PARAMETERS: sleep_state - Which sleep state we are exiting + * + * RETURN: Status + * + * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a + * sleep. + * Called with interrupts DISABLED. + * + ******************************************************************************/ +acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status; + struct acpi_bit_register_info *sleep_type_reg_info; + struct acpi_bit_register_info *sleep_enable_reg_info; + u32 PM1Acontrol; + u32 PM1Bcontrol; + + ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); + + /* + * Set SLP_TYPE and SLP_EN to state S0. + * This is unclear from the ACPI Spec, but it is required + * by some machines. + */ + status = acpi_get_sleep_type_data(ACPI_STATE_S0, + &acpi_gbl_sleep_type_a, + &acpi_gbl_sleep_type_b); + if (ACPI_SUCCESS(status)) { + sleep_type_reg_info = + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); + sleep_enable_reg_info = + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); + + /* Get current value of PM1A control */ + + status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, + &PM1Acontrol); + if (ACPI_SUCCESS(status)) { + + /* Clear SLP_EN and SLP_TYP fields */ + + PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | + sleep_enable_reg_info-> + access_bit_mask); + PM1Bcontrol = PM1Acontrol; + + /* Insert SLP_TYP bits */ + + PM1Acontrol |= + (acpi_gbl_sleep_type_a << sleep_type_reg_info-> + bit_position); + PM1Bcontrol |= + (acpi_gbl_sleep_type_b << sleep_type_reg_info-> + bit_position); + + /* Just ignore any errors */ + + (void)acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, + PM1Acontrol); + (void)acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, + PM1Bcontrol); + } + } + + /* Execute the _BFS method */ + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; + + status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_leave_sleep_state + * + * PARAMETERS: sleep_state - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. + * + ******************************************************************************/ +acpi_status acpi_leave_sleep_state(u8 sleep_state) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); + + /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ + + acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; + + /* Setup parameter object */ + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + + /* Ignore any errors from these methods */ + + arg.integer.value = ACPI_SST_WAKING; + status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); + } + + /* + * GPEs must be enabled before _WAK is called as GPEs + * might get fired there + * + * Restore the GPEs: + * 1) Disable/Clear all GPEs + * 2) Enable all runtime GPEs + */ + status = acpi_hw_disable_all_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + status = acpi_hw_enable_all_runtime_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + arg.integer.value = sleep_state; + status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); + } + /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ + + /* + * Some BIOSes assume that WAK_STS will be cleared on resume and use + * it to determine whether the system is rebooting or resuming. Clear + * it for compatibility. + */ + acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + + acpi_gbl_system_awake_and_running = TRUE; + + /* Enable power button */ + + (void) + acpi_set_register(acpi_gbl_fixed_event_info + [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1); + + (void) + acpi_set_register(acpi_gbl_fixed_event_info + [ACPI_EVENT_POWER_BUTTON].status_register_id, 1); + + arg.integer.value = ACPI_SST_WORKING; + status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); + } + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state) diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c new file mode 100644 index 000000000000..d1eac2aad728 --- /dev/null +++ b/drivers/acpi/acpica/hwtimer.c @@ -0,0 +1,188 @@ + +/****************************************************************************** + * + * Name: hwtimer.c - ACPI Power Management Timer Interface + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_HARDWARE +ACPI_MODULE_NAME("hwtimer") + +/****************************************************************************** + * + * FUNCTION: acpi_get_timer_resolution + * + * PARAMETERS: Resolution - Where the resolution is returned + * + * RETURN: Status and timer resolution + * + * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits). + * + ******************************************************************************/ +acpi_status acpi_get_timer_resolution(u32 * resolution) +{ + ACPI_FUNCTION_TRACE(acpi_get_timer_resolution); + + if (!resolution) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) { + *resolution = 24; + } else { + *resolution = 32; + } + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution) + +/****************************************************************************** + * + * FUNCTION: acpi_get_timer + * + * PARAMETERS: Ticks - Where the timer value is returned + * + * RETURN: Status and current timer value (ticks) + * + * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks). + * + ******************************************************************************/ +acpi_status acpi_get_timer(u32 * ticks) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_get_timer); + + if (!ticks) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = + acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT.xpm_timer_block); + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_timer) + +/****************************************************************************** + * + * FUNCTION: acpi_get_timer_duration + * + * PARAMETERS: start_ticks - Starting timestamp + * end_ticks - End timestamp + * time_elapsed - Where the elapsed time is returned + * + * RETURN: Status and time_elapsed + * + * DESCRIPTION: Computes the time elapsed (in microseconds) between two + * PM Timer time stamps, taking into account the possibility of + * rollovers, the timer resolution, and timer frequency. + * + * The PM Timer's clock ticks at roughly 3.6 times per + * _microsecond_, and its clock continues through Cx state + * transitions (unlike many CPU timestamp counters) -- making it + * a versatile and accurate timer. + * + * Note that this function accommodates only a single timer + * rollover. Thus for 24-bit timers, this function should only + * be used for calculating durations less than ~4.6 seconds + * (~20 minutes for 32-bit timers) -- calculations below: + * + * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec + * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes + * + ******************************************************************************/ +acpi_status +acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) +{ + acpi_status status; + u32 delta_ticks; + acpi_integer quotient; + + ACPI_FUNCTION_TRACE(acpi_get_timer_duration); + + if (!time_elapsed) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Compute Tick Delta: + * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. + */ + if (start_ticks < end_ticks) { + delta_ticks = end_ticks - start_ticks; + } else if (start_ticks > end_ticks) { + if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) { + + /* 24-bit Timer */ + + delta_ticks = + (((0x00FFFFFF - start_ticks) + + end_ticks) & 0x00FFFFFF); + } else { + /* 32-bit Timer */ + + delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks; + } + } else { /* start_ticks == end_ticks */ + + *time_elapsed = 0; + return_ACPI_STATUS(AE_OK); + } + + /* + * Compute Duration (Requires a 64-bit multiply and divide): + * + * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY; + */ + status = acpi_ut_short_divide(((u64) delta_ticks) * 1000000, + PM_TIMER_FREQUENCY, "ient, NULL); + + *time_elapsed = (u32) quotient; + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_timer_duration) diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c new file mode 100644 index 000000000000..a4456fc9462d --- /dev/null +++ b/drivers/acpi/acpica/hwxface.c @@ -0,0 +1,593 @@ + +/****************************************************************************** + * + * Module Name: hwxface - Public ACPICA hardware interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_HARDWARE +ACPI_MODULE_NAME("hwxface") + +/****************************************************************************** + * + * FUNCTION: acpi_reset + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Set reset register in memory or IO space. Note: Does not + * support reset register in PCI config space, this must be + * handled separately. + * + ******************************************************************************/ +acpi_status acpi_reset(void) +{ + struct acpi_generic_address *reset_reg; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_reset); + + reset_reg = &acpi_gbl_FADT.reset_register; + + /* Check if the reset register is supported */ + + if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || + !reset_reg->address) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Write the reset value to the reset register */ + + status = acpi_write(acpi_gbl_FADT.reset_value, reset_reg); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_reset) + +/****************************************************************************** + * + * FUNCTION: acpi_read + * + * PARAMETERS: Value - Where the value is returned + * Reg - GAS register structure + * + * RETURN: Status + * + * DESCRIPTION: Read from either memory or IO space. + * + ******************************************************************************/ +acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) +{ + u32 width; + u64 address; + acpi_status status; + + ACPI_FUNCTION_NAME(acpi_read); + + /* + * Must have a valid pointer to a GAS structure, and + * a non-zero address within. However, don't return an error + * because the PM1A/B code must not fail if B isn't present. + */ + if (!reg) { + return (AE_OK); + } + + /* Get a local copy of the address. Handles possible alignment issues */ + + ACPI_MOVE_64_TO_64(&address, ®->address); + if (!address) { + return (AE_OK); + } + + /* Supported widths are 8/16/32 */ + + width = reg->bit_width; + if ((width != 8) && (width != 16) && (width != 32)) { + return (AE_SUPPORT); + } + + /* Initialize entire 32-bit return value to zero */ + + *value = 0; + + /* + * Two address spaces supported: Memory or IO. + * PCI_Config is not supported here because the GAS struct is insufficient + */ + switch (reg->space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + + status = acpi_os_read_memory((acpi_physical_address) address, + value, width); + break; + + case ACPI_ADR_SPACE_SYSTEM_IO: + + status = + acpi_os_read_port((acpi_io_address) address, value, width); + break; + + default: + ACPI_ERROR((AE_INFO, + "Unsupported address space: %X", reg->space_id)); + return (AE_BAD_PARAMETER); + } + + ACPI_DEBUG_PRINT((ACPI_DB_IO, + "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", + *value, width, ACPI_FORMAT_UINT64(address), + acpi_ut_get_region_name(reg->space_id))); + + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_read) + +/****************************************************************************** + * + * FUNCTION: acpi_write + * + * PARAMETERS: Value - To be written + * Reg - GAS register structure + * + * RETURN: Status + * + * DESCRIPTION: Write to either memory or IO space. + * + ******************************************************************************/ +acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) +{ + u32 width; + u64 address; + acpi_status status; + + ACPI_FUNCTION_NAME(acpi_write); + + /* + * Must have a valid pointer to a GAS structure, and + * a non-zero address within. However, don't return an error + * because the PM1A/B code must not fail if B isn't present. + */ + if (!reg) { + return (AE_OK); + } + + /* Get a local copy of the address. Handles possible alignment issues */ + + ACPI_MOVE_64_TO_64(&address, ®->address); + if (!address) { + return (AE_OK); + } + + /* Supported widths are 8/16/32 */ + + width = reg->bit_width; + if ((width != 8) && (width != 16) && (width != 32)) { + return (AE_SUPPORT); + } + + /* + * Two address spaces supported: Memory or IO. + * PCI_Config is not supported here because the GAS struct is insufficient + */ + switch (reg->space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + + status = acpi_os_write_memory((acpi_physical_address) address, + value, width); + break; + + case ACPI_ADR_SPACE_SYSTEM_IO: + + status = acpi_os_write_port((acpi_io_address) address, value, + width); + break; + + default: + ACPI_ERROR((AE_INFO, + "Unsupported address space: %X", reg->space_id)); + return (AE_BAD_PARAMETER); + } + + ACPI_DEBUG_PRINT((ACPI_DB_IO, + "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", + value, width, ACPI_FORMAT_UINT64(address), + acpi_ut_get_region_name(reg->space_id))); + + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_write) + +/******************************************************************************* + * + * FUNCTION: acpi_get_register_unlocked + * + * PARAMETERS: register_id - ID of ACPI bit_register to access + * return_value - Value that was read from the register + * + * RETURN: Status and the value read from specified Register. Value + * returned is normalized to bit0 (is shifted all the way right) + * + * DESCRIPTION: ACPI bit_register read function. Does not acquire the HW lock. + * + ******************************************************************************/ +acpi_status acpi_get_register_unlocked(u32 register_id, u32 *return_value) +{ + u32 register_value = 0; + struct acpi_bit_register_info *bit_reg_info; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_get_register_unlocked); + + /* Get the info structure corresponding to the requested ACPI Register */ + + bit_reg_info = acpi_hw_get_bit_register_info(register_id); + if (!bit_reg_info) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Read from the register */ + + status = acpi_hw_register_read(bit_reg_info->parent_register, + ®ister_value); + + if (ACPI_SUCCESS(status)) { + + /* Normalize the value that was read */ + + register_value = + ((register_value & bit_reg_info->access_bit_mask) + >> bit_reg_info->bit_position); + + *return_value = register_value; + + ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read value %8.8X register %X\n", + register_value, + bit_reg_info->parent_register)); + } + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_register_unlocked) + +/******************************************************************************* + * + * FUNCTION: acpi_get_register + * + * PARAMETERS: register_id - ID of ACPI bit_register to access + * return_value - Value that was read from the register + * + * RETURN: Status and the value read from specified Register. Value + * returned is normalized to bit0 (is shifted all the way right) + * + * DESCRIPTION: ACPI bit_register read function. + * + ******************************************************************************/ +acpi_status acpi_get_register(u32 register_id, u32 *return_value) +{ + acpi_status status; + acpi_cpu_flags flags; + + flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); + status = acpi_get_register_unlocked(register_id, return_value); + acpi_os_release_lock(acpi_gbl_hardware_lock, flags); + + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_register) + +/******************************************************************************* + * + * FUNCTION: acpi_set_register + * + * PARAMETERS: register_id - ID of ACPI bit_register to access + * Value - (only used on write) value to write to the + * Register, NOT pre-normalized to the bit pos + * + * RETURN: Status + * + * DESCRIPTION: ACPI Bit Register write function. + * + ******************************************************************************/ +acpi_status acpi_set_register(u32 register_id, u32 value) +{ + u32 register_value = 0; + struct acpi_bit_register_info *bit_reg_info; + acpi_status status; + acpi_cpu_flags lock_flags; + + ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id); + + /* Get the info structure corresponding to the requested ACPI Register */ + + bit_reg_info = acpi_hw_get_bit_register_info(register_id); + if (!bit_reg_info) { + ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X", + register_id)); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); + + /* Always do a register read first so we can insert the new bits */ + + status = acpi_hw_register_read(bit_reg_info->parent_register, + ®ister_value); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* + * Decode the Register ID + * Register ID = [Register block ID] | [bit ID] + * + * Check bit ID to fine locate Register offset. + * Check Mask to determine Register offset, and then read-write. + */ + switch (bit_reg_info->parent_register) { + case ACPI_REGISTER_PM1_STATUS: + + /* + * Status Registers are different from the rest. Clear by + * writing 1, and writing 0 has no effect. So, the only relevant + * information is the single bit we're interested in, all others should + * be written as 0 so they will be left unchanged. + */ + value = ACPI_REGISTER_PREPARE_BITS(value, + bit_reg_info->bit_position, + bit_reg_info-> + access_bit_mask); + if (value) { + status = + acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, + (u16) value); + register_value = 0; + } + break; + + case ACPI_REGISTER_PM1_ENABLE: + + ACPI_REGISTER_INSERT_VALUE(register_value, + bit_reg_info->bit_position, + bit_reg_info->access_bit_mask, + value); + + status = acpi_hw_register_write(ACPI_REGISTER_PM1_ENABLE, + (u16) register_value); + break; + + case ACPI_REGISTER_PM1_CONTROL: + + /* + * Write the PM1 Control register. + * Note that at this level, the fact that there are actually TWO + * registers (A and B - and B may not exist) is abstracted. + */ + ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM1 control: Read %X\n", + register_value)); + + ACPI_REGISTER_INSERT_VALUE(register_value, + bit_reg_info->bit_position, + bit_reg_info->access_bit_mask, + value); + + status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, + (u16) register_value); + break; + + case ACPI_REGISTER_PM2_CONTROL: + + status = acpi_hw_register_read(ACPI_REGISTER_PM2_CONTROL, + ®ister_value); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + ACPI_DEBUG_PRINT((ACPI_DB_IO, + "PM2 control: Read %X from %8.8X%8.8X\n", + register_value, + ACPI_FORMAT_UINT64(acpi_gbl_FADT. + xpm2_control_block. + address))); + + ACPI_REGISTER_INSERT_VALUE(register_value, + bit_reg_info->bit_position, + bit_reg_info->access_bit_mask, + value); + + ACPI_DEBUG_PRINT((ACPI_DB_IO, + "About to write %4.4X to %8.8X%8.8X\n", + register_value, + ACPI_FORMAT_UINT64(acpi_gbl_FADT. + xpm2_control_block. + address))); + + status = acpi_hw_register_write(ACPI_REGISTER_PM2_CONTROL, + (u8) (register_value)); + break; + + default: + break; + } + + unlock_and_exit: + + acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); + + /* Normalize the value that was read */ + + ACPI_DEBUG_EXEC(register_value = + ((register_value & bit_reg_info->access_bit_mask) >> + bit_reg_info->bit_position)); + + ACPI_DEBUG_PRINT((ACPI_DB_IO, + "Set bits: %8.8X actual %8.8X register %X\n", value, + register_value, bit_reg_info->parent_register)); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_set_register) + +/******************************************************************************* + * + * FUNCTION: acpi_get_sleep_type_data + * + * PARAMETERS: sleep_state - Numeric sleep state + * *sleep_type_a - Where SLP_TYPa is returned + * *sleep_type_b - Where SLP_TYPb is returned + * + * RETURN: Status - ACPI status + * + * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep + * state. + * + ******************************************************************************/ +acpi_status +acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) +{ + acpi_status status = AE_OK; + struct acpi_evaluate_info *info; + + ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data); + + /* Validate parameters */ + + if ((sleep_state > ACPI_S_STATES_MAX) || !sleep_type_a || !sleep_type_b) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Allocate the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->pathname = + ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]); + + /* Evaluate the namespace object containing the values for this state */ + + status = acpi_ns_evaluate(info); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "%s while evaluating SleepState [%s]\n", + acpi_format_exception(status), + info->pathname)); + + goto cleanup; + } + + /* Must have a return object */ + + if (!info->return_object) { + ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]", + info->pathname)); + status = AE_NOT_EXIST; + } + + /* It must be of type Package */ + + else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) { + ACPI_ERROR((AE_INFO, + "Sleep State return object is not a Package")); + status = AE_AML_OPERAND_TYPE; + } + + /* + * The package must have at least two elements. NOTE (March 2005): This + * goes against the current ACPI spec which defines this object as a + * package with one encoded DWORD element. However, existing practice + * by BIOS vendors seems to be to have 2 or more elements, at least + * one per sleep type (A/B). + */ + else if (info->return_object->package.count < 2) { + ACPI_ERROR((AE_INFO, + "Sleep State return package does not have at least two elements")); + status = AE_AML_NO_OPERAND; + } + + /* The first two elements must both be of type Integer */ + + else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0]) + != ACPI_TYPE_INTEGER) || + (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1]) + != ACPI_TYPE_INTEGER)) { + ACPI_ERROR((AE_INFO, + "Sleep State return package elements are not both Integers (%s, %s)", + acpi_ut_get_object_type_name(info->return_object-> + package.elements[0]), + acpi_ut_get_object_type_name(info->return_object-> + package.elements[1]))); + status = AE_AML_OPERAND_TYPE; + } else { + /* Valid _Sx_ package size, type, and value */ + + *sleep_type_a = (u8) + (info->return_object->package.elements[0])->integer.value; + *sleep_type_b = (u8) + (info->return_object->package.elements[1])->integer.value; + } + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "While evaluating SleepState [%s], bad Sleep object %p type %s", + info->pathname, info->return_object, + acpi_ut_get_object_type_name(info-> + return_object))); + } + + acpi_ut_remove_reference(info->return_object); + + cleanup: + ACPI_FREE(info); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data) diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c new file mode 100644 index 000000000000..7954640e69cb --- /dev/null +++ b/drivers/acpi/acpica/nsaccess.c @@ -0,0 +1,676 @@ +/******************************************************************************* + * + * Module Name: nsaccess - Top-level functions for accessing ACPI namespace + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsaccess") + +/******************************************************************************* + * + * FUNCTION: acpi_ns_root_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Allocate and initialize the default root named objects + * + * MUTEX: Locks namespace for entire execution + * + ******************************************************************************/ +acpi_status acpi_ns_root_initialize(void) +{ + acpi_status status; + const struct acpi_predefined_names *init_val = NULL; + struct acpi_namespace_node *new_node; + union acpi_operand_object *obj_desc; + acpi_string val = NULL; + + ACPI_FUNCTION_TRACE(ns_root_initialize); + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * The global root ptr is initially NULL, so a non-NULL value indicates + * that acpi_ns_root_initialize() has already been called; just return. + */ + if (acpi_gbl_root_node) { + status = AE_OK; + goto unlock_and_exit; + } + + /* + * Tell the rest of the subsystem that the root is initialized + * (This is OK because the namespace is locked) + */ + acpi_gbl_root_node = &acpi_gbl_root_node_struct; + + /* Enter the pre-defined names in the name table */ + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Entering predefined entries into namespace\n")); + + for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { + + /* _OSI is optional for now, will be permanent later */ + + if (!ACPI_STRCMP(init_val->name, "_OSI") + && !acpi_gbl_create_osi_method) { + continue; + } + + status = acpi_ns_lookup(NULL, init_val->name, init_val->type, + ACPI_IMODE_LOAD_PASS2, + ACPI_NS_NO_UPSEARCH, NULL, &new_node); + + if (ACPI_FAILURE(status) || (!new_node)) { /* Must be on same line for code converter */ + ACPI_EXCEPTION((AE_INFO, status, + "Could not create predefined name %s", + init_val->name)); + } + + /* + * Name entered successfully. + * If entry in pre_defined_names[] specifies an + * initial value, create the initial value. + */ + if (init_val->val) { + status = acpi_os_predefined_override(init_val, &val); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not override predefined %s", + init_val->name)); + } + + if (!val) { + val = init_val->val; + } + + /* + * Entry requests an initial value, allocate a + * descriptor for it. + */ + obj_desc = + acpi_ut_create_internal_object(init_val->type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* + * Convert value string from table entry to + * internal representation. Only types actually + * used for initial values are implemented here. + */ + switch (init_val->type) { + case ACPI_TYPE_METHOD: + obj_desc->method.param_count = + (u8) ACPI_TO_INTEGER(val); + obj_desc->common.flags |= AOPOBJ_DATA_VALID; + +#if defined (ACPI_ASL_COMPILER) + + /* Save the parameter count for the i_aSL compiler */ + + new_node->value = obj_desc->method.param_count; +#else + /* Mark this as a very SPECIAL method */ + + obj_desc->method.method_flags = + AML_METHOD_INTERNAL_ONLY; + obj_desc->method.implementation = + acpi_ut_osi_implementation; +#endif + break; + + case ACPI_TYPE_INTEGER: + + obj_desc->integer.value = ACPI_TO_INTEGER(val); + break; + + case ACPI_TYPE_STRING: + + /* + * Build an object around the static string + */ + obj_desc->string.length = + (u32) ACPI_STRLEN(val); + obj_desc->string.pointer = val; + obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; + break; + + case ACPI_TYPE_MUTEX: + + obj_desc->mutex.node = new_node; + obj_desc->mutex.sync_level = + (u8) (ACPI_TO_INTEGER(val) - 1); + + /* Create a mutex */ + + status = + acpi_os_create_mutex(&obj_desc->mutex. + os_mutex); + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(obj_desc); + goto unlock_and_exit; + } + + /* Special case for ACPI Global Lock */ + + if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { + acpi_gbl_global_lock_mutex = obj_desc; + + /* Create additional counting semaphore for global lock */ + + status = + acpi_os_create_semaphore(1, 0, + &acpi_gbl_global_lock_semaphore); + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference + (obj_desc); + goto unlock_and_exit; + } + } + break; + + default: + + ACPI_ERROR((AE_INFO, + "Unsupported initial type value %X", + init_val->type)); + acpi_ut_remove_reference(obj_desc); + obj_desc = NULL; + continue; + } + + /* Store pointer to value descriptor in the Node */ + + status = acpi_ns_attach_object(new_node, obj_desc, + ACPI_GET_OBJECT_TYPE + (obj_desc)); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + } + } + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + + /* Save a handle to "_GPE", it is always present */ + + if (ACPI_SUCCESS(status)) { + status = acpi_ns_get_node(NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, + &acpi_gbl_fadt_gpe_device); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_lookup + * + * PARAMETERS: scope_info - Current scope info block + * Pathname - Search pathname, in internal format + * (as represented in the AML stream) + * Type - Type associated with name + * interpreter_mode - IMODE_LOAD_PASS2 => add name if not found + * Flags - Flags describing the search restrictions + * walk_state - Current state of the walk + * return_node - Where the Node is placed (if found + * or created successfully) + * + * RETURN: Status + * + * DESCRIPTION: Find or enter the passed name in the name space. + * Log an error if name not found in Exec mode. + * + * MUTEX: Assumes namespace is locked. + * + ******************************************************************************/ + +acpi_status +acpi_ns_lookup(union acpi_generic_state *scope_info, + char *pathname, + acpi_object_type type, + acpi_interpreter_mode interpreter_mode, + u32 flags, + struct acpi_walk_state *walk_state, + struct acpi_namespace_node **return_node) +{ + acpi_status status; + char *path = pathname; + struct acpi_namespace_node *prefix_node; + struct acpi_namespace_node *current_node = NULL; + struct acpi_namespace_node *this_node = NULL; + u32 num_segments; + u32 num_carats; + acpi_name simple_name; + acpi_object_type type_to_check_for; + acpi_object_type this_search_type; + u32 search_parent_flag = ACPI_NS_SEARCH_PARENT; + u32 local_flags; + + ACPI_FUNCTION_TRACE(ns_lookup); + + if (!return_node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); + *return_node = ACPI_ENTRY_NOT_FOUND; + acpi_gbl_ns_lookup_count++; + + if (!acpi_gbl_root_node) { + return_ACPI_STATUS(AE_NO_NAMESPACE); + } + + /* + * Get the prefix scope. + * A null scope means use the root scope + */ + if ((!scope_info) || (!scope_info->scope.node)) { + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Null scope prefix, using root node (%p)\n", + acpi_gbl_root_node)); + + prefix_node = acpi_gbl_root_node; + } else { + prefix_node = scope_info->scope.node; + if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) != + ACPI_DESC_TYPE_NAMED) { + ACPI_ERROR((AE_INFO, "%p is not a namespace node [%s]", + prefix_node, + acpi_ut_get_descriptor_name(prefix_node))); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) { + /* + * This node might not be a actual "scope" node (such as a + * Device/Method, etc.) It could be a Package or other object node. + * Backup up the tree to find the containing scope node. + */ + while (!acpi_ns_opens_scope(prefix_node->type) && + prefix_node->type != ACPI_TYPE_ANY) { + prefix_node = + acpi_ns_get_parent_node(prefix_node); + } + } + } + + /* Save type TBD: may be no longer necessary */ + + type_to_check_for = type; + + /* + * Begin examination of the actual pathname + */ + if (!pathname) { + + /* A Null name_path is allowed and refers to the root */ + + num_segments = 0; + this_node = acpi_gbl_root_node; + path = ""; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Null Pathname (Zero segments), Flags=%X\n", + flags)); + } else { + /* + * Name pointer is valid (and must be in internal name format) + * + * Check for scope prefixes: + * + * As represented in the AML stream, a namepath consists of an + * optional scope prefix followed by a name segment part. + * + * If present, the scope prefix is either a Root Prefix (in + * which case the name is fully qualified), or one or more + * Parent Prefixes (in which case the name's scope is relative + * to the current scope). + */ + if (*path == (u8) AML_ROOT_PREFIX) { + + /* Pathname is fully qualified, start from the root */ + + this_node = acpi_gbl_root_node; + search_parent_flag = ACPI_NS_NO_UPSEARCH; + + /* Point to name segment part */ + + path++; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Path is absolute from root [%p]\n", + this_node)); + } else { + /* Pathname is relative to current scope, start there */ + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Searching relative to prefix scope [%4.4s] (%p)\n", + acpi_ut_get_node_name(prefix_node), + prefix_node)); + + /* + * Handle multiple Parent Prefixes (carat) by just getting + * the parent node for each prefix instance. + */ + this_node = prefix_node; + num_carats = 0; + while (*path == (u8) AML_PARENT_PREFIX) { + + /* Name is fully qualified, no search rules apply */ + + search_parent_flag = ACPI_NS_NO_UPSEARCH; + /* + * Point past this prefix to the name segment + * part or the next Parent Prefix + */ + path++; + + /* Backup to the parent node */ + + num_carats++; + this_node = acpi_ns_get_parent_node(this_node); + if (!this_node) { + + /* Current scope has no parent scope */ + + ACPI_ERROR((AE_INFO, + "ACPI path has too many parent prefixes (^) - reached beyond root node")); + return_ACPI_STATUS(AE_NOT_FOUND); + } + } + + if (search_parent_flag == ACPI_NS_NO_UPSEARCH) { + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Search scope is [%4.4s], path has %d carat(s)\n", + acpi_ut_get_node_name + (this_node), num_carats)); + } + } + + /* + * Determine the number of ACPI name segments in this pathname. + * + * The segment part consists of either: + * - A Null name segment (0) + * - A dual_name_prefix followed by two 4-byte name segments + * - A multi_name_prefix followed by a byte indicating the + * number of segments and the segments themselves. + * - A single 4-byte name segment + * + * Examine the name prefix opcode, if any, to determine the number of + * segments. + */ + switch (*path) { + case 0: + /* + * Null name after a root or parent prefixes. We already + * have the correct target node and there are no name segments. + */ + num_segments = 0; + type = this_node->type; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Prefix-only Pathname (Zero name segments), Flags=%X\n", + flags)); + break; + + case AML_DUAL_NAME_PREFIX: + + /* More than one name_seg, search rules do not apply */ + + search_parent_flag = ACPI_NS_NO_UPSEARCH; + + /* Two segments, point to first name segment */ + + num_segments = 2; + path++; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Dual Pathname (2 segments, Flags=%X)\n", + flags)); + break; + + case AML_MULTI_NAME_PREFIX_OP: + + /* More than one name_seg, search rules do not apply */ + + search_parent_flag = ACPI_NS_NO_UPSEARCH; + + /* Extract segment count, point to first name segment */ + + path++; + num_segments = (u32) (u8) * path; + path++; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Multi Pathname (%d Segments, Flags=%X)\n", + num_segments, flags)); + break; + + default: + /* + * Not a Null name, no Dual or Multi prefix, hence there is + * only one name segment and Pathname is already pointing to it. + */ + num_segments = 1; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Simple Pathname (1 segment, Flags=%X)\n", + flags)); + break; + } + + ACPI_DEBUG_EXEC(acpi_ns_print_pathname(num_segments, path)); + } + + /* + * Search namespace for each segment of the name. Loop through and + * verify (or add to the namespace) each name segment. + * + * The object type is significant only at the last name + * segment. (We don't care about the types along the path, only + * the type of the final target object.) + */ + this_search_type = ACPI_TYPE_ANY; + current_node = this_node; + while (num_segments && current_node) { + num_segments--; + if (!num_segments) { + /* + * This is the last segment, enable typechecking + */ + this_search_type = type; + + /* + * Only allow automatic parent search (search rules) if the caller + * requested it AND we have a single, non-fully-qualified name_seg + */ + if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) && + (flags & ACPI_NS_SEARCH_PARENT)) { + local_flags |= ACPI_NS_SEARCH_PARENT; + } + + /* Set error flag according to caller */ + + if (flags & ACPI_NS_ERROR_IF_FOUND) { + local_flags |= ACPI_NS_ERROR_IF_FOUND; + } + } + + /* Extract one ACPI name from the front of the pathname */ + + ACPI_MOVE_32_TO_32(&simple_name, path); + + /* Try to find the single (4 character) ACPI name */ + + status = + acpi_ns_search_and_enter(simple_name, walk_state, + current_node, interpreter_mode, + this_search_type, local_flags, + &this_node); + if (ACPI_FAILURE(status)) { + if (status == AE_NOT_FOUND) { + + /* Name not found in ACPI namespace */ + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Name [%4.4s] not found in scope [%4.4s] %p\n", + (char *)&simple_name, + (char *)¤t_node->name, + current_node)); + } + + *return_node = this_node; + return_ACPI_STATUS(status); + } + + /* More segments to follow? */ + + if (num_segments > 0) { + /* + * If we have an alias to an object that opens a scope (such as a + * device or processor), we need to dereference the alias here so that + * we can access any children of the original node (via the remaining + * segments). + */ + if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) { + if (!this_node->object) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + if (acpi_ns_opens_scope + (((struct acpi_namespace_node *)this_node-> + object)->type)) { + this_node = + (struct acpi_namespace_node *) + this_node->object; + } + } + } + + /* Special handling for the last segment (num_segments == 0) */ + + else { + /* + * Sanity typecheck of the target object: + * + * If 1) This is the last segment (num_segments == 0) + * 2) And we are looking for a specific type + * (Not checking for TYPE_ANY) + * 3) Which is not an alias + * 4) Which is not a local type (TYPE_SCOPE) + * 5) And the type of target object is known (not TYPE_ANY) + * 6) And target object does not match what we are looking for + * + * Then we have a type mismatch. Just warn and ignore it. + */ + if ((type_to_check_for != ACPI_TYPE_ANY) && + (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && + (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) + && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) + && (this_node->type != ACPI_TYPE_ANY) + && (this_node->type != type_to_check_for)) { + + /* Complain about a type mismatch */ + + ACPI_WARNING((AE_INFO, + "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", + ACPI_CAST_PTR(char, &simple_name), + acpi_ut_get_type_name(this_node-> + type), + acpi_ut_get_type_name + (type_to_check_for))); + } + + /* + * If this is the last name segment and we are not looking for a + * specific type, but the type of found object is known, use that type + * to (later) see if it opens a scope. + */ + if (type == ACPI_TYPE_ANY) { + type = this_node->type; + } + } + + /* Point to next name segment and make this node current */ + + path += ACPI_NAME_SIZE; + current_node = this_node; + } + + /* + * Always check if we need to open a new scope + */ + if (!(flags & ACPI_NS_DONT_OPEN_SCOPE) && (walk_state)) { + /* + * If entry is a type which opens a scope, push the new scope on the + * scope stack. + */ + if (acpi_ns_opens_scope(type)) { + status = + acpi_ds_scope_stack_push(this_node, type, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + } + + *return_node = this_node; + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c new file mode 100644 index 000000000000..cb2afbf4e457 --- /dev/null +++ b/drivers/acpi/acpica/nsalloc.c @@ -0,0 +1,497 @@ +/******************************************************************************* + * + * Module Name: nsalloc - Namespace allocation and deletion utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsalloc") + +/******************************************************************************* + * + * FUNCTION: acpi_ns_create_node + * + * PARAMETERS: Name - Name of the new node (4 char ACPI name) + * + * RETURN: New namespace node (Null on failure) + * + * DESCRIPTION: Create a namespace node + * + ******************************************************************************/ +struct acpi_namespace_node *acpi_ns_create_node(u32 name) +{ + struct acpi_namespace_node *node; +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + u32 temp; +#endif + + ACPI_FUNCTION_TRACE(ns_create_node); + + node = acpi_os_acquire_object(acpi_gbl_namespace_cache); + if (!node) { + return_PTR(NULL); + } + + ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++); + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + temp = + acpi_gbl_ns_node_list->total_allocated - + acpi_gbl_ns_node_list->total_freed; + if (temp > acpi_gbl_ns_node_list->max_occupied) { + acpi_gbl_ns_node_list->max_occupied = temp; + } +#endif + + node->name.integer = name; + ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED); + return_PTR(node); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_delete_node + * + * PARAMETERS: Node - Node to be deleted + * + * RETURN: None + * + * DESCRIPTION: Delete a namespace node + * + ******************************************************************************/ + +void acpi_ns_delete_node(struct acpi_namespace_node *node) +{ + struct acpi_namespace_node *parent_node; + struct acpi_namespace_node *prev_node; + struct acpi_namespace_node *next_node; + + ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node); + + parent_node = acpi_ns_get_parent_node(node); + + prev_node = NULL; + next_node = parent_node->child; + + /* Find the node that is the previous peer in the parent's child list */ + + while (next_node != node) { + prev_node = next_node; + next_node = prev_node->peer; + } + + if (prev_node) { + + /* Node is not first child, unlink it */ + + prev_node->peer = next_node->peer; + if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + prev_node->flags |= ANOBJ_END_OF_PEER_LIST; + } + } else { + /* Node is first child (has no previous peer) */ + + if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + + /* No peers at all */ + + parent_node->child = NULL; + } else { /* Link peer list to parent */ + + parent_node->child = next_node->peer; + } + } + + ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); + + /* + * Detach an object if there is one, then delete the node + */ + acpi_ns_detach_object(node); + (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_install_node + * + * PARAMETERS: walk_state - Current state of the walk + * parent_node - The parent of the new Node + * Node - The new Node to install + * Type - ACPI object type of the new Node + * + * RETURN: None + * + * DESCRIPTION: Initialize a new namespace node and install it amongst + * its peers. + * + * Note: Current namespace lookup is linear search. This appears + * to be sufficient as namespace searches consume only a small + * fraction of the execution time of the ACPI subsystem. + * + ******************************************************************************/ + +void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namespace_node *parent_node, /* Parent */ + struct acpi_namespace_node *node, /* New Child */ + acpi_object_type type) +{ + acpi_owner_id owner_id = 0; + struct acpi_namespace_node *child_node; + + ACPI_FUNCTION_TRACE(ns_install_node); + + /* + * Get the owner ID from the Walk state + * The owner ID is used to track table deletion and + * deletion of objects created by methods + */ + if (walk_state) { + owner_id = walk_state->owner_id; + } + + /* Link the new entry into the parent and existing children */ + + child_node = parent_node->child; + if (!child_node) { + parent_node->child = node; + node->flags |= ANOBJ_END_OF_PEER_LIST; + node->peer = parent_node; + } else { + while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) { + child_node = child_node->peer; + } + + child_node->peer = node; + + /* Clear end-of-list flag */ + + child_node->flags &= ~ANOBJ_END_OF_PEER_LIST; + node->flags |= ANOBJ_END_OF_PEER_LIST; + node->peer = parent_node; + } + + /* Init the new entry */ + + node->owner_id = owner_id; + node->type = (u8) type; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n", + acpi_ut_get_node_name(node), + acpi_ut_get_type_name(node->type), node, owner_id, + acpi_ut_get_node_name(parent_node), + acpi_ut_get_type_name(parent_node->type), + parent_node)); + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_delete_children + * + * PARAMETERS: parent_node - Delete this objects children + * + * RETURN: None. + * + * DESCRIPTION: Delete all children of the parent object. In other words, + * deletes a "scope". + * + ******************************************************************************/ + +void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) +{ + struct acpi_namespace_node *child_node; + struct acpi_namespace_node *next_node; + u8 flags; + + ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node); + + if (!parent_node) { + return_VOID; + } + + /* If no children, all done! */ + + child_node = parent_node->child; + if (!child_node) { + return_VOID; + } + + /* + * Deallocate all children at this level + */ + do { + + /* Get the things we need */ + + next_node = child_node->peer; + flags = child_node->flags; + + /* Grandchildren should have all been deleted already */ + + if (child_node->child) { + ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p", + parent_node, child_node)); + } + + /* Now we can free this child object */ + + ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "Object %p, Remaining %X\n", child_node, + acpi_gbl_current_node_count)); + + /* + * Detach an object if there is one, then free the child node + */ + acpi_ns_detach_object(child_node); + + /* Now we can delete the node */ + + (void)acpi_os_release_object(acpi_gbl_namespace_cache, + child_node); + + /* And move on to the next child in the list */ + + child_node = next_node; + + } while (!(flags & ANOBJ_END_OF_PEER_LIST)); + + /* Clear the parent's child pointer */ + + parent_node->child = NULL; + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_delete_namespace_subtree + * + * PARAMETERS: parent_node - Root of the subtree to be deleted + * + * RETURN: None. + * + * DESCRIPTION: Delete a subtree of the namespace. This includes all objects + * stored within the subtree. + * + ******************************************************************************/ + +void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) +{ + struct acpi_namespace_node *child_node = NULL; + u32 level = 1; + + ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree); + + if (!parent_node) { + return_VOID; + } + + /* + * Traverse the tree of objects until we bubble back up + * to where we started. + */ + while (level > 0) { + + /* Get the next node in this scope (NULL if none) */ + + child_node = + acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, + child_node); + if (child_node) { + + /* Found a child node - detach any attached object */ + + acpi_ns_detach_object(child_node); + + /* Check if this node has any children */ + + if (acpi_ns_get_next_node + (ACPI_TYPE_ANY, child_node, NULL)) { + /* + * There is at least one child of this node, + * visit the node + */ + level++; + parent_node = child_node; + child_node = NULL; + } + } else { + /* + * No more children of this parent node. + * Move up to the grandparent. + */ + level--; + + /* + * Now delete all of the children of this parent + * all at the same time. + */ + acpi_ns_delete_children(parent_node); + + /* New "last child" is this parent node */ + + child_node = parent_node; + + /* Move up the tree to the grandparent */ + + parent_node = acpi_ns_get_parent_node(parent_node); + } + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_delete_namespace_by_owner + * + * PARAMETERS: owner_id - All nodes with this owner will be deleted + * + * RETURN: Status + * + * DESCRIPTION: Delete entries within the namespace that are owned by a + * specific ID. Used to delete entire ACPI tables. All + * reference counts are updated. + * + * MUTEX: Locks namespace during deletion walk. + * + ******************************************************************************/ + +void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) +{ + struct acpi_namespace_node *child_node; + struct acpi_namespace_node *deletion_node; + struct acpi_namespace_node *parent_node; + u32 level; + acpi_status status; + + ACPI_FUNCTION_TRACE_U32(ns_delete_namespace_by_owner, owner_id); + + if (owner_id == 0) { + return_VOID; + } + + /* Lock namespace for possible update */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_VOID; + } + + deletion_node = NULL; + parent_node = acpi_gbl_root_node; + child_node = NULL; + level = 1; + + /* + * Traverse the tree of nodes until we bubble back up + * to where we started. + */ + while (level > 0) { + /* + * Get the next child of this parent node. When child_node is NULL, + * the first child of the parent is returned + */ + child_node = + acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, + child_node); + + if (deletion_node) { + acpi_ns_delete_children(deletion_node); + acpi_ns_delete_node(deletion_node); + deletion_node = NULL; + } + + if (child_node) { + if (child_node->owner_id == owner_id) { + + /* Found a matching child node - detach any attached object */ + + acpi_ns_detach_object(child_node); + } + + /* Check if this node has any children */ + + if (acpi_ns_get_next_node + (ACPI_TYPE_ANY, child_node, NULL)) { + /* + * There is at least one child of this node, + * visit the node + */ + level++; + parent_node = child_node; + child_node = NULL; + } else if (child_node->owner_id == owner_id) { + deletion_node = child_node; + } + } else { + /* + * No more children of this parent node. + * Move up to the grandparent. + */ + level--; + if (level != 0) { + if (parent_node->owner_id == owner_id) { + deletion_node = parent_node; + } + } + + /* New "last child" is this parent node */ + + child_node = parent_node; + + /* Move up the tree to the grandparent */ + + parent_node = acpi_ns_get_parent_node(parent_node); + } + } + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_VOID; +} diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c new file mode 100644 index 000000000000..48f02e659f24 --- /dev/null +++ b/drivers/acpi/acpica/nsdump.c @@ -0,0 +1,709 @@ +/****************************************************************************** + * + * Module Name: nsdump - table dumping routines for debug + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsdump") + +/* Local prototypes */ +#ifdef ACPI_OBSOLETE_FUNCTIONS +void acpi_ns_dump_root_devices(void); + +static acpi_status +acpi_ns_dump_one_device(acpi_handle obj_handle, + u32 level, void *context, void **return_value); +#endif + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/******************************************************************************* + * + * FUNCTION: acpi_ns_print_pathname + * + * PARAMETERS: num_segments - Number of ACPI name segments + * Pathname - The compressed (internal) path + * + * RETURN: None + * + * DESCRIPTION: Print an object's full namespace pathname + * + ******************************************************************************/ + +void acpi_ns_print_pathname(u32 num_segments, char *pathname) +{ + u32 i; + + ACPI_FUNCTION_NAME(ns_print_pathname); + + if (!(acpi_dbg_level & ACPI_LV_NAMES) + || !(acpi_dbg_layer & ACPI_NAMESPACE)) { + return; + } + + /* Print the entire name */ + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "[")); + + while (num_segments) { + for (i = 0; i < 4; i++) { + ACPI_IS_PRINT(pathname[i]) ? + acpi_os_printf("%c", pathname[i]) : + acpi_os_printf("?"); + } + + pathname += ACPI_NAME_SIZE; + num_segments--; + if (num_segments) { + acpi_os_printf("."); + } + } + + acpi_os_printf("]\n"); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_pathname + * + * PARAMETERS: Handle - Object + * Msg - Prefix message + * Level - Desired debug level + * Component - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Print an object's full namespace pathname + * Manages allocation/freeing of a pathname buffer + * + ******************************************************************************/ + +void +acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component) +{ + + ACPI_FUNCTION_TRACE(ns_dump_pathname); + + /* Do this only if the requested debug level and component are enabled */ + + if (!(acpi_dbg_level & level) || !(acpi_dbg_layer & component)) { + return_VOID; + } + + /* Convert handle to a full pathname and print it (with supplied message) */ + + acpi_ns_print_node_pathname(handle, msg); + acpi_os_printf("\n"); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_one_object + * + * PARAMETERS: obj_handle - Node to be dumped + * Level - Nesting level of the handle + * Context - Passed into walk_namespace + * return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Dump a single Node + * This procedure is a user_function called by acpi_ns_walk_namespace. + * + ******************************************************************************/ + +acpi_status +acpi_ns_dump_one_object(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + struct acpi_walk_info *info = (struct acpi_walk_info *)context; + struct acpi_namespace_node *this_node; + union acpi_operand_object *obj_desc = NULL; + acpi_object_type obj_type; + acpi_object_type type; + u32 bytes_to_dump; + u32 dbg_level; + u32 i; + + ACPI_FUNCTION_NAME(ns_dump_one_object); + + /* Is output enabled? */ + + if (!(acpi_dbg_level & info->debug_level)) { + return (AE_OK); + } + + if (!obj_handle) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Null object handle\n")); + return (AE_OK); + } + + this_node = acpi_ns_map_handle_to_node(obj_handle); + type = this_node->type; + + /* Check if the owner matches */ + + if ((info->owner_id != ACPI_OWNER_ID_MAX) && + (info->owner_id != this_node->owner_id)) { + return (AE_OK); + } + + if (!(info->display_type & ACPI_DISPLAY_SHORT)) { + + /* Indent the object according to the level */ + + acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " "); + + /* Check the node type and name */ + + if (type > ACPI_TYPE_LOCAL_MAX) { + ACPI_WARNING((AE_INFO, "Invalid ACPI Object Type %08X", + type)); + } + + if (!acpi_ut_valid_acpi_name(this_node->name.integer)) { + this_node->name.integer = + acpi_ut_repair_name(this_node->name.ascii); + + ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X", + this_node->name.integer)); + } + + acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node)); + } + + /* + * Now we can print out the pertinent information + */ + acpi_os_printf(" %-12s %p %2.2X ", + acpi_ut_get_type_name(type), this_node, + this_node->owner_id); + + dbg_level = acpi_dbg_level; + acpi_dbg_level = 0; + obj_desc = acpi_ns_get_attached_object(this_node); + acpi_dbg_level = dbg_level; + + /* Temp nodes are those nodes created by a control method */ + + if (this_node->flags & ANOBJ_TEMPORARY) { + acpi_os_printf("(T) "); + } + + switch (info->display_type & ACPI_DISPLAY_MASK) { + case ACPI_DISPLAY_SUMMARY: + + if (!obj_desc) { + + /* No attached object, we are done */ + + acpi_os_printf("\n"); + return (AE_OK); + } + + switch (type) { + case ACPI_TYPE_PROCESSOR: + + acpi_os_printf("ID %X Len %.4X Addr %p\n", + obj_desc->processor.proc_id, + obj_desc->processor.length, + ACPI_CAST_PTR(void, + obj_desc->processor. + address)); + break; + + case ACPI_TYPE_DEVICE: + + acpi_os_printf("Notify Object: %p\n", obj_desc); + break; + + case ACPI_TYPE_METHOD: + + acpi_os_printf("Args %X Len %.4X Aml %p\n", + (u32) obj_desc->method.param_count, + obj_desc->method.aml_length, + obj_desc->method.aml_start); + break; + + case ACPI_TYPE_INTEGER: + + acpi_os_printf("= %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(obj_desc->integer. + value)); + break; + + case ACPI_TYPE_PACKAGE: + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + acpi_os_printf("Elements %.2X\n", + obj_desc->package.count); + } else { + acpi_os_printf("[Length not yet evaluated]\n"); + } + break; + + case ACPI_TYPE_BUFFER: + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + acpi_os_printf("Len %.2X", + obj_desc->buffer.length); + + /* Dump some of the buffer */ + + if (obj_desc->buffer.length > 0) { + acpi_os_printf(" ="); + for (i = 0; + (i < obj_desc->buffer.length + && i < 12); i++) { + acpi_os_printf(" %.2hX", + obj_desc->buffer. + pointer[i]); + } + } + acpi_os_printf("\n"); + } else { + acpi_os_printf("[Length not yet evaluated]\n"); + } + break; + + case ACPI_TYPE_STRING: + + acpi_os_printf("Len %.2X ", obj_desc->string.length); + acpi_ut_print_string(obj_desc->string.pointer, 32); + acpi_os_printf("\n"); + break; + + case ACPI_TYPE_REGION: + + acpi_os_printf("[%s]", + acpi_ut_get_region_name(obj_desc->region. + space_id)); + if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { + acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n", + ACPI_FORMAT_NATIVE_UINT + (obj_desc->region.address), + obj_desc->region.length); + } else { + acpi_os_printf + (" [Address/Length not yet evaluated]\n"); + } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + acpi_os_printf("[%s]\n", + acpi_ut_get_reference_name(obj_desc)); + break; + + case ACPI_TYPE_BUFFER_FIELD: + + if (obj_desc->buffer_field.buffer_obj && + obj_desc->buffer_field.buffer_obj->buffer.node) { + acpi_os_printf("Buf [%4.4s]", + acpi_ut_get_node_name(obj_desc-> + buffer_field. + buffer_obj-> + buffer. + node)); + } + break; + + case ACPI_TYPE_LOCAL_REGION_FIELD: + + acpi_os_printf("Rgn [%4.4s]", + acpi_ut_get_node_name(obj_desc-> + common_field. + region_obj->region. + node)); + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + acpi_os_printf("Rgn [%4.4s] Bnk [%4.4s]", + acpi_ut_get_node_name(obj_desc-> + common_field. + region_obj->region. + node), + acpi_ut_get_node_name(obj_desc-> + bank_field. + bank_obj-> + common_field. + node)); + break; + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + acpi_os_printf("Idx [%4.4s] Dat [%4.4s]", + acpi_ut_get_node_name(obj_desc-> + index_field. + index_obj-> + common_field.node), + acpi_ut_get_node_name(obj_desc-> + index_field. + data_obj-> + common_field. + node)); + break; + + case ACPI_TYPE_LOCAL_ALIAS: + case ACPI_TYPE_LOCAL_METHOD_ALIAS: + + acpi_os_printf("Target %4.4s (%p)\n", + acpi_ut_get_node_name(obj_desc), + obj_desc); + break; + + default: + + acpi_os_printf("Object %p\n", obj_desc); + break; + } + + /* Common field handling */ + + switch (type) { + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + acpi_os_printf(" Off %.3X Len %.2X Acc %.2hd\n", + (obj_desc->common_field. + base_byte_offset * 8) + + + obj_desc->common_field. + start_field_bit_offset, + obj_desc->common_field.bit_length, + obj_desc->common_field. + access_byte_width); + break; + + default: + break; + } + break; + + case ACPI_DISPLAY_OBJECTS: + + acpi_os_printf("O:%p", obj_desc); + if (!obj_desc) { + + /* No attached object, we are done */ + + acpi_os_printf("\n"); + return (AE_OK); + } + + acpi_os_printf("(R%d)", obj_desc->common.reference_count); + + switch (type) { + case ACPI_TYPE_METHOD: + + /* Name is a Method and its AML offset/length are set */ + + acpi_os_printf(" M:%p-%X\n", obj_desc->method.aml_start, + obj_desc->method.aml_length); + break; + + case ACPI_TYPE_INTEGER: + + acpi_os_printf(" I:%8.8X8.8%X\n", + ACPI_FORMAT_UINT64(obj_desc->integer. + value)); + break; + + case ACPI_TYPE_STRING: + + acpi_os_printf(" S:%p-%X\n", obj_desc->string.pointer, + obj_desc->string.length); + break; + + case ACPI_TYPE_BUFFER: + + acpi_os_printf(" B:%p-%X\n", obj_desc->buffer.pointer, + obj_desc->buffer.length); + break; + + default: + + acpi_os_printf("\n"); + break; + } + break; + + default: + acpi_os_printf("\n"); + break; + } + + /* If debug turned off, done */ + + if (!(acpi_dbg_level & ACPI_LV_VALUES)) { + return (AE_OK); + } + + /* If there is an attached object, display it */ + + dbg_level = acpi_dbg_level; + acpi_dbg_level = 0; + obj_desc = acpi_ns_get_attached_object(this_node); + acpi_dbg_level = dbg_level; + + /* Dump attached objects */ + + while (obj_desc) { + obj_type = ACPI_TYPE_INVALID; + acpi_os_printf("Attached Object %p: ", obj_desc); + + /* Decode the type of attached object and dump the contents */ + + switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { + case ACPI_DESC_TYPE_NAMED: + + acpi_os_printf("(Ptr to Node)\n"); + bytes_to_dump = sizeof(struct acpi_namespace_node); + ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump); + break; + + case ACPI_DESC_TYPE_OPERAND: + + obj_type = ACPI_GET_OBJECT_TYPE(obj_desc); + + if (obj_type > ACPI_TYPE_LOCAL_MAX) { + acpi_os_printf + ("(Pointer to ACPI Object type %.2X [UNKNOWN])\n", + obj_type); + bytes_to_dump = 32; + } else { + acpi_os_printf + ("(Pointer to ACPI Object type %.2X [%s])\n", + obj_type, acpi_ut_get_type_name(obj_type)); + bytes_to_dump = + sizeof(union acpi_operand_object); + } + + ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump); + break; + + default: + + break; + } + + /* If value is NOT an internal object, we are done */ + + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != + ACPI_DESC_TYPE_OPERAND) { + goto cleanup; + } + + /* + * Valid object, get the pointer to next level, if any + */ + switch (obj_type) { + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_STRING: + /* + * NOTE: takes advantage of common fields between string/buffer + */ + bytes_to_dump = obj_desc->string.length; + obj_desc = (void *)obj_desc->string.pointer; + acpi_os_printf("(Buffer/String pointer %p length %X)\n", + obj_desc, bytes_to_dump); + ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump); + goto cleanup; + + case ACPI_TYPE_BUFFER_FIELD: + obj_desc = + (union acpi_operand_object *)obj_desc->buffer_field. + buffer_obj; + break; + + case ACPI_TYPE_PACKAGE: + obj_desc = (void *)obj_desc->package.elements; + break; + + case ACPI_TYPE_METHOD: + obj_desc = (void *)obj_desc->method.aml_start; + break; + + case ACPI_TYPE_LOCAL_REGION_FIELD: + obj_desc = (void *)obj_desc->field.region_obj; + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + obj_desc = (void *)obj_desc->bank_field.region_obj; + break; + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + obj_desc = (void *)obj_desc->index_field.index_obj; + break; + + default: + goto cleanup; + } + + obj_type = ACPI_TYPE_INVALID; /* Terminate loop after next pass */ + } + + cleanup: + acpi_os_printf("\n"); + return (AE_OK); +} + +#ifdef ACPI_FUTURE_USAGE +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_objects + * + * PARAMETERS: Type - Object type to be dumped + * display_type - 0 or ACPI_DISPLAY_SUMMARY + * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX + * for an effectively unlimited depth. + * owner_id - Dump only objects owned by this ID. Use + * ACPI_UINT32_MAX to match all owners. + * start_handle - Where in namespace to start/end search + * + * RETURN: None + * + * DESCRIPTION: Dump typed objects within the loaded namespace. + * Uses acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object. + * + ******************************************************************************/ + +void +acpi_ns_dump_objects(acpi_object_type type, + u8 display_type, + u32 max_depth, + acpi_owner_id owner_id, acpi_handle start_handle) +{ + struct acpi_walk_info info; + + ACPI_FUNCTION_ENTRY(); + + info.debug_level = ACPI_LV_TABLES; + info.owner_id = owner_id; + info.display_type = display_type; + + (void)acpi_ns_walk_namespace(type, start_handle, max_depth, + ACPI_NS_WALK_NO_UNLOCK | + ACPI_NS_WALK_TEMP_NODES, + acpi_ns_dump_one_object, (void *)&info, + NULL); +} +#endif /* ACPI_FUTURE_USAGE */ + +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_entry + * + * PARAMETERS: Handle - Node to be dumped + * debug_level - Output level + * + * RETURN: None + * + * DESCRIPTION: Dump a single Node + * + ******************************************************************************/ + +void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level) +{ + struct acpi_walk_info info; + + ACPI_FUNCTION_ENTRY(); + + info.debug_level = debug_level; + info.owner_id = ACPI_OWNER_ID_MAX; + info.display_type = ACPI_DISPLAY_SUMMARY; + + (void)acpi_ns_dump_one_object(handle, 1, &info, NULL); +} + +#ifdef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_tables + * + * PARAMETERS: search_base - Root of subtree to be dumped, or + * NS_ALL to dump the entire namespace + * max_depth - Maximum depth of dump. Use INT_MAX + * for an effectively unlimited depth. + * + * RETURN: None + * + * DESCRIPTION: Dump the name space, or a portion of it. + * + ******************************************************************************/ + +void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth) +{ + acpi_handle search_handle = search_base; + + ACPI_FUNCTION_TRACE(ns_dump_tables); + + if (!acpi_gbl_root_node) { + /* + * If the name space has not been initialized, + * there is nothing to dump. + */ + ACPI_DEBUG_PRINT((ACPI_DB_TABLES, + "namespace not initialized!\n")); + return_VOID; + } + + if (ACPI_NS_ALL == search_base) { + + /* Entire namespace */ + + search_handle = acpi_gbl_root_node; + ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "\\\n")); + } + + acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, max_depth, + ACPI_OWNER_ID_MAX, search_handle); + return_VOID; +} +#endif /* _ACPI_ASL_COMPILER */ +#endif /* defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) */ diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c new file mode 100644 index 000000000000..cc3df78258ed --- /dev/null +++ b/drivers/acpi/acpica/nsdumpdv.c @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * Module Name: nsdump - table dumping routines for debug + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +/* TBD: This entire module is apparently obsolete and should be removed */ + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsdumpdv") +#ifdef ACPI_OBSOLETE_FUNCTIONS +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +#include +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_one_device + * + * PARAMETERS: Handle - Node to be dumped + * Level - Nesting level of the handle + * Context - Passed into walk_namespace + * return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Dump a single Node that represents a device + * This procedure is a user_function called by acpi_ns_walk_namespace. + * + ******************************************************************************/ +static acpi_status +acpi_ns_dump_one_device(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + struct acpi_buffer buffer; + struct acpi_device_info *info; + acpi_status status; + u32 i; + + ACPI_FUNCTION_NAME(ns_dump_one_device); + + status = + acpi_ns_dump_one_object(obj_handle, level, context, return_value); + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_get_object_info(obj_handle, &buffer); + if (ACPI_SUCCESS(status)) { + info = buffer.pointer; + for (i = 0; i < level; i++) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " ")); + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, + " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", + info->hardware_id.value, + ACPI_FORMAT_UINT64(info->address), + info->current_status)); + ACPI_FREE(info); + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_root_devices + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Dump all objects of type "device" + * + ******************************************************************************/ + +void acpi_ns_dump_root_devices(void) +{ + acpi_handle sys_bus_handle; + acpi_status status; + + ACPI_FUNCTION_NAME(ns_dump_root_devices); + + /* Only dump the table if tracing is enabled */ + + if (!(ACPI_LV_TABLES & acpi_dbg_level)) { + return; + } + + status = acpi_get_handle(NULL, ACPI_NS_SYSTEM_BUS, &sys_bus_handle); + if (ACPI_FAILURE(status)) { + return; + } + + ACPI_DEBUG_PRINT((ACPI_DB_TABLES, + "Display of all devices in the namespace:\n")); + + status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, sys_bus_handle, + ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, + acpi_ns_dump_one_device, NULL, NULL); +} + +#endif +#endif diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c new file mode 100644 index 000000000000..a8d7764c73b7 --- /dev/null +++ b/drivers/acpi/acpica/nseval.c @@ -0,0 +1,278 @@ +/******************************************************************************* + * + * Module Name: nseval - Object evaluation, includes control method execution + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nseval") + +/******************************************************************************* + * + * FUNCTION: acpi_ns_evaluate + * + * PARAMETERS: Info - Evaluation info block, contains: + * prefix_node - Prefix or Method/Object Node to execute + * Pathname - Name of method to execute, If NULL, the + * Node is the object to execute + * Parameters - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * parameter_type - Type of Parameter list + * return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * Flags - ACPI_IGNORE_RETURN_VALUE to delete return + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method or return the current value of an + * ACPI namespace object. + * + * MUTEX: Locks interpreter + * + ******************************************************************************/ +acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) +{ + acpi_status status; + struct acpi_namespace_node *node; + + ACPI_FUNCTION_TRACE(ns_evaluate); + + if (!info) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Initialize the return value to an invalid object */ + + info->return_object = NULL; + info->param_count = 0; + + /* + * Get the actual namespace node for the target object. Handles these cases: + * + * 1) Null node, Pathname (absolute path) + * 2) Node, Pathname (path relative to Node) + * 3) Node, Null Pathname + */ + status = acpi_ns_get_node(info->prefix_node, info->pathname, + ACPI_NS_NO_UPSEARCH, &info->resolved_node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * For a method alias, we must grab the actual method node so that proper + * scoping context will be established before execution. + */ + if (acpi_ns_get_type(info->resolved_node) == + ACPI_TYPE_LOCAL_METHOD_ALIAS) { + info->resolved_node = + ACPI_CAST_PTR(struct acpi_namespace_node, + info->resolved_node->object); + } + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname, + info->resolved_node, + acpi_ns_get_attached_object(info->resolved_node))); + + node = info->resolved_node; + + /* + * Two major cases here: + * + * 1) The object is a control method -- execute it + * 2) The object is not a method -- just return it's current value + */ + if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) { + /* + * 1) Object is a control method - execute it + */ + + /* Verify that there is a method object associated with this node */ + + info->obj_desc = + acpi_ns_get_attached_object(info->resolved_node); + if (!info->obj_desc) { + ACPI_ERROR((AE_INFO, + "Control method has no attached sub-object")); + return_ACPI_STATUS(AE_NULL_OBJECT); + } + + /* Count the number of arguments being passed to the method */ + + if (info->parameters) { + while (info->parameters[info->param_count]) { + if (info->param_count > ACPI_METHOD_MAX_ARG) { + return_ACPI_STATUS(AE_LIMIT); + } + info->param_count++; + } + } + + + ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:", + ACPI_LV_INFO, _COMPONENT); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Method at AML address %p Length %X\n", + info->obj_desc->method.aml_start + 1, + info->obj_desc->method.aml_length - 1)); + + /* + * Any namespace deletion must acquire both the namespace and + * interpreter locks to ensure that no thread is using the portion of + * the namespace that is being deleted. + * + * Execute the method via the interpreter. The interpreter is locked + * here before calling into the AML parser + */ + acpi_ex_enter_interpreter(); + status = acpi_ps_execute_method(info); + acpi_ex_exit_interpreter(); + } else { + /* + * 2) Object is not a method, return its current value + * + * Disallow certain object types. For these, "evaluation" is undefined. + */ + switch (info->resolved_node->type) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_REGION: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_LOCAL_SCOPE: + + ACPI_ERROR((AE_INFO, + "[%4.4s] Evaluation of object type [%s] is not supported", + info->resolved_node->name.ascii, + acpi_ut_get_type_name(info->resolved_node-> + type))); + + return_ACPI_STATUS(AE_TYPE); + + default: + break; + } + + /* + * Objects require additional resolution steps (e.g., the Node may be + * a field that must be read, etc.) -- we can't just grab the object + * out of the node. + * + * Use resolve_node_to_value() to get the associated value. + * + * NOTE: we can get away with passing in NULL for a walk state because + * resolved_node is guaranteed to not be a reference to either a method + * local or a method argument (because this interface is never called + * from a running method.) + * + * Even though we do not directly invoke the interpreter for object + * resolution, we must lock it because we could access an opregion. + * The opregion access code assumes that the interpreter is locked. + */ + acpi_ex_enter_interpreter(); + + /* Function has a strange interface */ + + status = + acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); + acpi_ex_exit_interpreter(); + + /* + * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed + * in resolved_node. + */ + if (ACPI_SUCCESS(status)) { + status = AE_CTRL_RETURN_VALUE; + info->return_object = + ACPI_CAST_PTR(union acpi_operand_object, + info->resolved_node); + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Returning object %p [%s]\n", + info->return_object, + acpi_ut_get_object_type_name(info-> + return_object))); + } + } + + /* + * Check input argument count against the ASL-defined count for a method. + * Also check predefined names: argument count and return value against + * the ACPI specification. Some incorrect return value types are repaired. + */ + (void)acpi_ns_check_predefined_names(node, info->param_count, + status, &info->return_object); + + /* Check if there is a return value that must be dealt with */ + + if (status == AE_CTRL_RETURN_VALUE) { + + /* If caller does not want the return value, delete it */ + + if (info->flags & ACPI_IGNORE_RETURN_VALUE) { + acpi_ut_remove_reference(info->return_object); + info->return_object = NULL; + } + + /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ + + status = AE_OK; + } + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "*** Completed evaluation of object %s ***\n", + info->pathname)); + + /* + * Namespace was unlocked by the handling acpi_ns* function, so we + * just return + */ + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c new file mode 100644 index 000000000000..fe470c4b38f7 --- /dev/null +++ b/drivers/acpi/acpica/nsinit.c @@ -0,0 +1,593 @@ +/****************************************************************************** + * + * Module Name: nsinit - namespace initialization + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsinit") + +/* Local prototypes */ +static acpi_status +acpi_ns_init_one_object(acpi_handle obj_handle, + u32 level, void *context, void **return_value); + +static acpi_status +acpi_ns_init_one_device(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value); + +static acpi_status +acpi_ns_find_ini_methods(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value); + +/******************************************************************************* + * + * FUNCTION: acpi_ns_initialize_objects + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Walk the entire namespace and perform any necessary + * initialization on the objects found therein + * + ******************************************************************************/ + +acpi_status acpi_ns_initialize_objects(void) +{ + acpi_status status; + struct acpi_init_walk_info info; + + ACPI_FUNCTION_TRACE(ns_initialize_objects); + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "**** Starting initialization of namespace objects ****\n")); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + "Completing Region/Field/Buffer/Package initialization:")); + + /* Set all init info to zero */ + + ACPI_MEMSET(&info, 0, sizeof(struct acpi_init_walk_info)); + + /* Walk entire namespace from the supplied root */ + + status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_ns_init_one_object, + &info, NULL); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd Buffers %hd/%hd Packages (%hd nodes)\n", + info.op_region_init, info.op_region_count, + info.field_init, info.field_count, + info.buffer_init, info.buffer_count, + info.package_init, info.package_count, + info.object_count)); + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "%hd Control Methods found\n", info.method_count)); + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "%hd Op Regions found\n", info.op_region_count)); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_initialize_devices + * + * PARAMETERS: None + * + * RETURN: acpi_status + * + * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices. + * This means running _INI on all present devices. + * + * Note: We install PCI config space handler on region access, + * not here. + * + ******************************************************************************/ + +acpi_status acpi_ns_initialize_devices(void) +{ + acpi_status status; + struct acpi_device_walk_info info; + + ACPI_FUNCTION_TRACE(ns_initialize_devices); + + /* Init counters */ + + info.device_count = 0; + info.num_STA = 0; + info.num_INI = 0; + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + "Initializing Device/Processor/Thermal objects by executing _INI methods:")); + + /* Tree analysis: find all subtrees that contain _INI methods */ + + status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, + acpi_ns_find_ini_methods, &info, NULL); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + + /* Allocate the evaluation information block */ + + info.evaluate_info = + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info.evaluate_info) { + status = AE_NO_MEMORY; + goto error_exit; + } + + /* Walk namespace to execute all _INIs on present devices */ + + status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, + acpi_ns_init_one_device, &info, NULL); + + ACPI_FREE(info.evaluate_info); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + "\nExecuted %hd _INI methods requiring %hd _STA executions (examined %hd objects)\n", + info.num_INI, info.num_STA, info.device_count)); + + return_ACPI_STATUS(status); + + error_exit: + ACPI_EXCEPTION((AE_INFO, status, "During device initialization")); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_init_one_object + * + * PARAMETERS: obj_handle - Node + * Level - Current nesting level + * Context - Points to a init info struct + * return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object + * within the namespace. + * + * Currently, the only objects that require initialization are: + * 1) Methods + * 2) Op Regions + * + ******************************************************************************/ + +static acpi_status +acpi_ns_init_one_object(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + acpi_object_type type; + acpi_status status = AE_OK; + struct acpi_init_walk_info *info = + (struct acpi_init_walk_info *)context; + struct acpi_namespace_node *node = + (struct acpi_namespace_node *)obj_handle; + union acpi_operand_object *obj_desc; + + ACPI_FUNCTION_NAME(ns_init_one_object); + + info->object_count++; + + /* And even then, we are only interested in a few object types */ + + type = acpi_ns_get_type(obj_handle); + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return (AE_OK); + } + + /* Increment counters for object types we are looking for */ + + switch (type) { + case ACPI_TYPE_REGION: + info->op_region_count++; + break; + + case ACPI_TYPE_BUFFER_FIELD: + info->field_count++; + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + info->field_count++; + break; + + case ACPI_TYPE_BUFFER: + info->buffer_count++; + break; + + case ACPI_TYPE_PACKAGE: + info->package_count++; + break; + + default: + + /* No init required, just exit now */ + return (AE_OK); + } + + /* + * If the object is already initialized, nothing else to do + */ + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return (AE_OK); + } + + /* + * Must lock the interpreter before executing AML code + */ + acpi_ex_enter_interpreter(); + + /* + * Each of these types can contain executable AML code within the + * declaration. + */ + switch (type) { + case ACPI_TYPE_REGION: + + info->op_region_init++; + status = acpi_ds_get_region_arguments(obj_desc); + break; + + case ACPI_TYPE_BUFFER_FIELD: + + info->field_init++; + status = acpi_ds_get_buffer_field_arguments(obj_desc); + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + info->field_init++; + status = acpi_ds_get_bank_field_arguments(obj_desc); + break; + + case ACPI_TYPE_BUFFER: + + info->buffer_init++; + status = acpi_ds_get_buffer_arguments(obj_desc); + break; + + case ACPI_TYPE_PACKAGE: + + info->package_init++; + status = acpi_ds_get_package_arguments(obj_desc); + break; + + default: + /* No other types can get here */ + break; + } + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not execute arguments for [%4.4s] (%s)", + acpi_ut_get_node_name(node), + acpi_ut_get_type_name(type))); + } + + /* + * Print a dot for each object unless we are going to print the entire + * pathname + */ + if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); + } + + /* + * We ignore errors from above, and always return OK, since we don't want + * to abort the walk on any single error. + */ + acpi_ex_exit_interpreter(); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_find_ini_methods + * + * PARAMETERS: acpi_walk_callback + * + * RETURN: acpi_status + * + * DESCRIPTION: Called during namespace walk. Finds objects named _INI under + * device/processor/thermal objects, and marks the entire subtree + * with a SUBTREE_HAS_INI flag. This flag is used during the + * subsequent device initialization walk to avoid entire subtrees + * that do not contain an _INI. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_find_ini_methods(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value) +{ + struct acpi_device_walk_info *info = + ACPI_CAST_PTR(struct acpi_device_walk_info, context); + struct acpi_namespace_node *node; + struct acpi_namespace_node *parent_node; + + /* Keep count of device/processor/thermal objects */ + + node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); + if ((node->type == ACPI_TYPE_DEVICE) || + (node->type == ACPI_TYPE_PROCESSOR) || + (node->type == ACPI_TYPE_THERMAL)) { + info->device_count++; + return (AE_OK); + } + + /* We are only looking for methods named _INI */ + + if (!ACPI_COMPARE_NAME(node->name.ascii, METHOD_NAME__INI)) { + return (AE_OK); + } + + /* + * The only _INI methods that we care about are those that are + * present under Device, Processor, and Thermal objects. + */ + parent_node = acpi_ns_get_parent_node(node); + switch (parent_node->type) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* Mark parent and bubble up the INI present flag to the root */ + + while (parent_node) { + parent_node->flags |= ANOBJ_SUBTREE_HAS_INI; + parent_node = acpi_ns_get_parent_node(parent_node); + } + break; + + default: + break; + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_init_one_device + * + * PARAMETERS: acpi_walk_callback + * + * RETURN: acpi_status + * + * DESCRIPTION: This is called once per device soon after ACPI is enabled + * to initialize each device. It determines if the device is + * present, and if so, calls _INI. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_init_one_device(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value) +{ + struct acpi_device_walk_info *walk_info = + ACPI_CAST_PTR(struct acpi_device_walk_info, context); + struct acpi_evaluate_info *info = walk_info->evaluate_info; + u32 flags; + acpi_status status; + struct acpi_namespace_node *device_node; + + ACPI_FUNCTION_TRACE(ns_init_one_device); + + /* We are interested in Devices, Processors and thermal_zones only */ + + device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); + if ((device_node->type != ACPI_TYPE_DEVICE) && + (device_node->type != ACPI_TYPE_PROCESSOR) && + (device_node->type != ACPI_TYPE_THERMAL)) { + return_ACPI_STATUS(AE_OK); + } + + /* + * Because of an earlier namespace analysis, all subtrees that contain an + * _INI method are tagged. + * + * If this device subtree does not contain any _INI methods, we + * can exit now and stop traversing this entire subtree. + */ + if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) { + return_ACPI_STATUS(AE_CTRL_DEPTH); + } + + /* + * Run _STA to determine if this device is present and functioning. We + * must know this information for two important reasons (from ACPI spec): + * + * 1) We can only run _INI if the device is present. + * 2) We must abort the device tree walk on this subtree if the device is + * not present and is not functional (we will not examine the children) + * + * The _STA method is not required to be present under the device, we + * assume the device is present if _STA does not exist. + */ + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA)); + + status = acpi_ut_execute_STA(device_node, &flags); + if (ACPI_FAILURE(status)) { + + /* Ignore error and move on to next device */ + + return_ACPI_STATUS(AE_OK); + } + + /* + * Flags == -1 means that _STA was not found. In this case, we assume that + * the device is both present and functional. + * + * From the ACPI spec, description of _STA: + * + * "If a device object (including the processor object) does not have an + * _STA object, then OSPM assumes that all of the above bits are set (in + * other words, the device is present, ..., and functioning)" + */ + if (flags != ACPI_UINT32_MAX) { + walk_info->num_STA++; + } + + /* + * Examine the PRESENT and FUNCTIONING status bits + * + * Note: ACPI spec does not seem to specify behavior for the present but + * not functioning case, so we assume functioning if present. + */ + if (!(flags & ACPI_STA_DEVICE_PRESENT)) { + + /* Device is not present, we must examine the Functioning bit */ + + if (flags & ACPI_STA_DEVICE_FUNCTIONING) { + /* + * Device is not present but is "functioning". In this case, + * we will not run _INI, but we continue to examine the children + * of this device. + * + * From the ACPI spec, description of _STA: (Note - no mention + * of whether to run _INI or not on the device in question) + * + * "_STA may return bit 0 clear (not present) with bit 3 set + * (device is functional). This case is used to indicate a valid + * device for which no device driver should be loaded (for example, + * a bridge device.) Children of this device may be present and + * valid. OSPM should continue enumeration below a device whose + * _STA returns this bit combination" + */ + return_ACPI_STATUS(AE_OK); + } else { + /* + * Device is not present and is not functioning. We must abort the + * walk of this subtree immediately -- don't look at the children + * of such a device. + * + * From the ACPI spec, description of _INI: + * + * "If the _STA method indicates that the device is not present, + * OSPM will not run the _INI and will not examine the children + * of the device for _INI methods" + */ + return_ACPI_STATUS(AE_CTRL_DEPTH); + } + } + + /* + * The device is present or is assumed present if no _STA exists. + * Run the _INI if it exists (not required to exist) + * + * Note: We know there is an _INI within this subtree, but it may not be + * under this particular device, it may be lower in the branch. + */ + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI)); + + info->prefix_node = device_node; + info->pathname = METHOD_NAME__INI; + info->parameters = NULL; + info->flags = ACPI_IGNORE_RETURN_VALUE; + + /* + * Some hardware relies on this being executed as atomically + * as possible (without an NMI being received in the middle of + * this) - so disable NMIs and initialize the device: + */ + acpi_nmi_disable(); + status = acpi_ns_evaluate(info); + acpi_nmi_enable(); + + if (ACPI_SUCCESS(status)) { + walk_info->num_INI++; + + if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && + (!(acpi_dbg_level & ACPI_LV_INFO))) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); + } + } +#ifdef ACPI_DEBUG_OUTPUT + else if (status != AE_NOT_FOUND) { + + /* Ignore error and move on to next device */ + + char *scope_name = + acpi_ns_get_external_pathname(info->resolved_node); + + ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution", + scope_name)); + ACPI_FREE(scope_name); + } +#endif + + /* Ignore errors from above */ + + status = AE_OK; + + /* + * The _INI method has been run if present; call the Global Initialization + * Handler for this device. + */ + if (acpi_gbl_init_handler) { + status = + acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI); + } + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c new file mode 100644 index 000000000000..a6e92b31a06f --- /dev/null +++ b/drivers/acpi/acpica/nsload.c @@ -0,0 +1,315 @@ +/****************************************************************************** + * + * Module Name: nsload - namespace loading/expanding/contracting procedures + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsload") + +/* Local prototypes */ +#ifdef ACPI_FUTURE_IMPLEMENTATION +acpi_status acpi_ns_unload_namespace(acpi_handle handle); + +static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle); +#endif + +#ifndef ACPI_NO_METHOD_EXECUTION +/******************************************************************************* + * + * FUNCTION: acpi_ns_load_table + * + * PARAMETERS: table_index - Index for table to be loaded + * Node - Owning NS node + * + * RETURN: Status + * + * DESCRIPTION: Load one ACPI table into the namespace + * + ******************************************************************************/ + +acpi_status +acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ns_load_table); + + /* + * Parse the table and load the namespace with all named + * objects found within. Control methods are NOT parsed + * at this time. In fact, the control methods cannot be + * parsed until the entire namespace is loaded, because + * if a control method makes a forward reference (call) + * to another control method, we can't continue parsing + * because we don't know how many arguments to parse next! + */ + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* If table already loaded into namespace, just return */ + + if (acpi_tb_is_table_loaded(table_index)) { + status = AE_ALREADY_EXISTS; + goto unlock; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "**** Loading table into namespace ****\n")); + + status = acpi_tb_allocate_owner_id(table_index); + if (ACPI_FAILURE(status)) { + goto unlock; + } + + status = acpi_ns_parse_table(table_index, node); + if (ACPI_SUCCESS(status)) { + acpi_tb_set_table_loaded_flag(table_index, TRUE); + } else { + (void)acpi_tb_release_owner_id(table_index); + } + + unlock: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Now we can parse the control methods. We always parse + * them here for a sanity check, and if configured for + * just-in-time parsing, we delete the control method + * parse trees. + */ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "**** Begin Table Method Parsing and Object Initialization ****\n")); + + status = acpi_ds_initialize_objects(table_index, node); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "**** Completed Table Method Parsing and Object Initialization ****\n")); + + return_ACPI_STATUS(status); +} + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: acpi_load_namespace + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. + * (DSDT points to either the BIOS or a buffer.) + * + ******************************************************************************/ + +acpi_status acpi_ns_load_namespace(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_load_name_space); + + /* There must be at least a DSDT installed */ + + if (acpi_gbl_DSDT == NULL) { + ACPI_ERROR((AE_INFO, "DSDT is not in memory")); + return_ACPI_STATUS(AE_NO_ACPI_TABLES); + } + + /* + * Load the namespace. The DSDT is required, + * but the SSDT and PSDT tables are optional. + */ + status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Ignore exceptions from these */ + + (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT); + (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT); + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + "ACPI Namespace successfully loaded at root %p\n", + acpi_gbl_root_node)); + + return_ACPI_STATUS(status); +} +#endif + +#ifdef ACPI_FUTURE_IMPLEMENTATION +/******************************************************************************* + * + * FUNCTION: acpi_ns_delete_subtree + * + * PARAMETERS: start_handle - Handle in namespace where search begins + * + * RETURNS Status + * + * DESCRIPTION: Walks the namespace starting at the given handle and deletes + * all objects, entries, and scopes in the entire subtree. + * + * Namespace/Interpreter should be locked or the subsystem should + * be in shutdown before this routine is called. + * + ******************************************************************************/ + +static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) +{ + acpi_status status; + acpi_handle child_handle; + acpi_handle parent_handle; + acpi_handle next_child_handle; + acpi_handle dummy; + u32 level; + + ACPI_FUNCTION_TRACE(ns_delete_subtree); + + parent_handle = start_handle; + child_handle = NULL; + level = 1; + + /* + * Traverse the tree of objects until we bubble back up + * to where we started. + */ + while (level > 0) { + + /* Attempt to get the next object in this scope */ + + status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, + child_handle, &next_child_handle); + + child_handle = next_child_handle; + + /* Did we get a new object? */ + + if (ACPI_SUCCESS(status)) { + + /* Check if this object has any children */ + + if (ACPI_SUCCESS + (acpi_get_next_object + (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) { + /* + * There is at least one child of this object, + * visit the object + */ + level++; + parent_handle = child_handle; + child_handle = NULL; + } + } else { + /* + * No more children in this object, go back up to + * the object's parent + */ + level--; + + /* Delete all children now */ + + acpi_ns_delete_children(child_handle); + + child_handle = parent_handle; + status = acpi_get_parent(parent_handle, &parent_handle); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + } + + /* Now delete the starting object, and we are done */ + + acpi_ns_delete_node(child_handle); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_unload_name_space + * + * PARAMETERS: Handle - Root of namespace subtree to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Shrinks the namespace, typically in response to an undocking + * event. Deletes an entire subtree starting from (and + * including) the given handle. + * + ******************************************************************************/ + +acpi_status acpi_ns_unload_namespace(acpi_handle handle) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ns_unload_name_space); + + /* Parameter validation */ + + if (!acpi_gbl_root_node) { + return_ACPI_STATUS(AE_NO_NAMESPACE); + } + + if (!handle) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* This function does the real work */ + + status = acpi_ns_delete_subtree(handle); + + return_ACPI_STATUS(status); +} +#endif +#endif diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c new file mode 100644 index 000000000000..b7e301848ba7 --- /dev/null +++ b/drivers/acpi/acpica/nsnames.c @@ -0,0 +1,265 @@ +/******************************************************************************* + * + * Module Name: nsnames - Name manipulation and search + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsnames") + +/******************************************************************************* + * + * FUNCTION: acpi_ns_build_external_path + * + * PARAMETERS: Node - NS node whose pathname is needed + * Size - Size of the pathname + * *name_buffer - Where to return the pathname + * + * RETURN: Status + * Places the pathname into the name_buffer, in external format + * (name segments separated by path separators) + * + * DESCRIPTION: Generate a full pathaname + * + ******************************************************************************/ +acpi_status +acpi_ns_build_external_path(struct acpi_namespace_node *node, + acpi_size size, char *name_buffer) +{ + acpi_size index; + struct acpi_namespace_node *parent_node; + + ACPI_FUNCTION_ENTRY(); + + /* Special case for root */ + + index = size - 1; + if (index < ACPI_NAME_SIZE) { + name_buffer[0] = AML_ROOT_PREFIX; + name_buffer[1] = 0; + return (AE_OK); + } + + /* Store terminator byte, then build name backwards */ + + parent_node = node; + name_buffer[index] = 0; + + while ((index > ACPI_NAME_SIZE) && (parent_node != acpi_gbl_root_node)) { + index -= ACPI_NAME_SIZE; + + /* Put the name into the buffer */ + + ACPI_MOVE_32_TO_32((name_buffer + index), &parent_node->name); + parent_node = acpi_ns_get_parent_node(parent_node); + + /* Prefix name with the path separator */ + + index--; + name_buffer[index] = ACPI_PATH_SEPARATOR; + } + + /* Overwrite final separator with the root prefix character */ + + name_buffer[index] = AML_ROOT_PREFIX; + + if (index != 0) { + ACPI_ERROR((AE_INFO, + "Could not construct external pathname; index=%X, size=%X, Path=%s", + (u32) index, (u32) size, &name_buffer[size])); + + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_external_pathname + * + * PARAMETERS: Node - Namespace node whose pathname is needed + * + * RETURN: Pointer to storage containing the fully qualified name of + * the node, In external format (name segments separated by path + * separators.) + * + * DESCRIPTION: Used for debug printing in acpi_ns_search_table(). + * + ******************************************************************************/ + +char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) +{ + acpi_status status; + char *name_buffer; + acpi_size size; + + ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node); + + /* Calculate required buffer size based on depth below root */ + + size = acpi_ns_get_pathname_length(node); + if (!size) { + return_PTR(NULL); + } + + /* Allocate a buffer to be returned to caller */ + + name_buffer = ACPI_ALLOCATE_ZEROED(size); + if (!name_buffer) { + ACPI_ERROR((AE_INFO, "Allocation failure")); + return_PTR(NULL); + } + + /* Build the path in the allocated buffer */ + + status = acpi_ns_build_external_path(node, size, name_buffer); + if (ACPI_FAILURE(status)) { + ACPI_FREE(name_buffer); + return_PTR(NULL); + } + + return_PTR(name_buffer); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_pathname_length + * + * PARAMETERS: Node - Namespace node + * + * RETURN: Length of path, including prefix + * + * DESCRIPTION: Get the length of the pathname string for this node + * + ******************************************************************************/ + +acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) +{ + acpi_size size; + struct acpi_namespace_node *next_node; + + ACPI_FUNCTION_ENTRY(); + + /* + * Compute length of pathname as 5 * number of name segments. + * Go back up the parent tree to the root + */ + size = 0; + next_node = node; + + while (next_node && (next_node != acpi_gbl_root_node)) { + if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) { + ACPI_ERROR((AE_INFO, + "Invalid Namespace Node (%p) while traversing namespace", + next_node)); + return 0; + } + size += ACPI_PATH_SEGMENT_LENGTH; + next_node = acpi_ns_get_parent_node(next_node); + } + + if (!size) { + size = 1; /* Root node case */ + } + + return (size + 1); /* +1 for null string terminator */ +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_handle_to_pathname + * + * PARAMETERS: target_handle - Handle of named object whose name is + * to be found + * Buffer - Where the pathname is returned + * + * RETURN: Status, Buffer is filled with pathname if status is AE_OK + * + * DESCRIPTION: Build and return a full namespace pathname + * + ******************************************************************************/ + +acpi_status +acpi_ns_handle_to_pathname(acpi_handle target_handle, + struct acpi_buffer * buffer) +{ + acpi_status status; + struct acpi_namespace_node *node; + acpi_size required_size; + + ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle); + + node = acpi_ns_map_handle_to_node(target_handle); + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Determine size required for the caller buffer */ + + required_size = acpi_ns_get_pathname_length(node); + if (!required_size) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer(buffer, required_size); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Build the path in the caller buffer */ + + status = + acpi_ns_build_external_path(node, required_size, buffer->pointer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n", + (char *)buffer->pointer, (u32) required_size)); + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c new file mode 100644 index 000000000000..ca9edeea27df --- /dev/null +++ b/drivers/acpi/acpica/nsobject.c @@ -0,0 +1,441 @@ +/******************************************************************************* + * + * Module Name: nsobject - Utilities for objects attached to namespace + * table entries + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsobject") + +/******************************************************************************* + * + * FUNCTION: acpi_ns_attach_object + * + * PARAMETERS: Node - Parent Node + * Object - Object to be attached + * Type - Type of object, or ACPI_TYPE_ANY if not + * known + * + * RETURN: Status + * + * DESCRIPTION: Record the given object as the value associated with the + * name whose acpi_handle is passed. If Object is NULL + * and Type is ACPI_TYPE_ANY, set the name as having no value. + * Note: Future may require that the Node->Flags field be passed + * as a parameter. + * + * MUTEX: Assumes namespace is locked + * + ******************************************************************************/ +acpi_status +acpi_ns_attach_object(struct acpi_namespace_node *node, + union acpi_operand_object *object, acpi_object_type type) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *last_obj_desc; + acpi_object_type object_type = ACPI_TYPE_ANY; + + ACPI_FUNCTION_TRACE(ns_attach_object); + + /* + * Parameter validation + */ + if (!node) { + + /* Invalid handle */ + + ACPI_ERROR((AE_INFO, "Null NamedObj handle")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (!object && (ACPI_TYPE_ANY != type)) { + + /* Null object */ + + ACPI_ERROR((AE_INFO, + "Null object, but type not ACPI_TYPE_ANY")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { + + /* Not a name handle */ + + ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]", + node, acpi_ut_get_descriptor_name(node))); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Check if this object is already attached */ + + if (node->object == object) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Obj %p already installed in NameObj %p\n", + object, node)); + + return_ACPI_STATUS(AE_OK); + } + + /* If null object, we will just install it */ + + if (!object) { + obj_desc = NULL; + object_type = ACPI_TYPE_ANY; + } + + /* + * If the source object is a namespace Node with an attached object, + * we will use that (attached) object + */ + else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) && + ((struct acpi_namespace_node *)object)->object) { + /* + * Value passed is a name handle and that name has a + * non-null value. Use that name's value and type. + */ + obj_desc = ((struct acpi_namespace_node *)object)->object; + object_type = ((struct acpi_namespace_node *)object)->type; + } + + /* + * Otherwise, we will use the parameter object, but we must type + * it first + */ + else { + obj_desc = (union acpi_operand_object *)object; + + /* Use the given type */ + + object_type = type; + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n", + obj_desc, node, acpi_ut_get_node_name(node))); + + /* Detach an existing attached object if present */ + + if (node->object) { + acpi_ns_detach_object(node); + } + + if (obj_desc) { + /* + * Must increment the new value's reference count + * (if it is an internal object) + */ + acpi_ut_add_reference(obj_desc); + + /* + * Handle objects with multiple descriptors - walk + * to the end of the descriptor list + */ + last_obj_desc = obj_desc; + while (last_obj_desc->common.next_object) { + last_obj_desc = last_obj_desc->common.next_object; + } + + /* Install the object at the front of the object list */ + + last_obj_desc->common.next_object = node->object; + } + + node->type = (u8) object_type; + node->object = obj_desc; + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_detach_object + * + * PARAMETERS: Node - A Namespace node whose object will be detached + * + * RETURN: None. + * + * DESCRIPTION: Detach/delete an object associated with a namespace node. + * if the object is an allocated object, it is freed. + * Otherwise, the field is simply cleared. + * + ******************************************************************************/ + +void acpi_ns_detach_object(struct acpi_namespace_node *node) +{ + union acpi_operand_object *obj_desc; + + ACPI_FUNCTION_TRACE(ns_detach_object); + + obj_desc = node->object; + + if (!obj_desc || + (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA)) { + return_VOID; + } + + /* Clear the entry in all cases */ + + node->object = NULL; + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) { + node->object = obj_desc->common.next_object; + if (node->object && + (ACPI_GET_OBJECT_TYPE(node->object) != + ACPI_TYPE_LOCAL_DATA)) { + node->object = node->object->common.next_object; + } + } + + /* Reset the node type to untyped */ + + node->type = ACPI_TYPE_ANY; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n", + node, acpi_ut_get_node_name(node), obj_desc)); + + /* Remove one reference on the object (and all subobjects) */ + + acpi_ut_remove_reference(obj_desc); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_attached_object + * + * PARAMETERS: Node - Namespace node + * + * RETURN: Current value of the object field from the Node whose + * handle is passed + * + * DESCRIPTION: Obtain the object attached to a namespace node. + * + ******************************************************************************/ + +union acpi_operand_object *acpi_ns_get_attached_object(struct + acpi_namespace_node + *node) +{ + ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node); + + if (!node) { + ACPI_WARNING((AE_INFO, "Null Node ptr")); + return_PTR(NULL); + } + + if (!node->object || + ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND) + && (ACPI_GET_DESCRIPTOR_TYPE(node->object) != + ACPI_DESC_TYPE_NAMED)) + || (ACPI_GET_OBJECT_TYPE(node->object) == ACPI_TYPE_LOCAL_DATA)) { + return_PTR(NULL); + } + + return_PTR(node->object); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_secondary_object + * + * PARAMETERS: Node - Namespace node + * + * RETURN: Current value of the object field from the Node whose + * handle is passed. + * + * DESCRIPTION: Obtain a secondary object associated with a namespace node. + * + ******************************************************************************/ + +union acpi_operand_object *acpi_ns_get_secondary_object(union + acpi_operand_object + *obj_desc) +{ + ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc); + + if ((!obj_desc) || + (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) || + (!obj_desc->common.next_object) || + (ACPI_GET_OBJECT_TYPE(obj_desc->common.next_object) == + ACPI_TYPE_LOCAL_DATA)) { + return_PTR(NULL); + } + + return_PTR(obj_desc->common.next_object); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_attach_data + * + * PARAMETERS: Node - Namespace node + * Handler - Handler to be associated with the data + * Data - Data to be attached + * + * RETURN: Status + * + * DESCRIPTION: Low-level attach data. Create and attach a Data object. + * + ******************************************************************************/ + +acpi_status +acpi_ns_attach_data(struct acpi_namespace_node *node, + acpi_object_handler handler, void *data) +{ + union acpi_operand_object *prev_obj_desc; + union acpi_operand_object *obj_desc; + union acpi_operand_object *data_desc; + + /* We only allow one attachment per handler */ + + prev_obj_desc = NULL; + obj_desc = node->object; + while (obj_desc) { + if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && + (obj_desc->data.handler == handler)) { + return (AE_ALREADY_EXISTS); + } + + prev_obj_desc = obj_desc; + obj_desc = obj_desc->common.next_object; + } + + /* Create an internal object for the data */ + + data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA); + if (!data_desc) { + return (AE_NO_MEMORY); + } + + data_desc->data.handler = handler; + data_desc->data.pointer = data; + + /* Install the data object */ + + if (prev_obj_desc) { + prev_obj_desc->common.next_object = data_desc; + } else { + node->object = data_desc; + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_detach_data + * + * PARAMETERS: Node - Namespace node + * Handler - Handler associated with the data + * + * RETURN: Status + * + * DESCRIPTION: Low-level detach data. Delete the data node, but the caller + * is responsible for the actual data. + * + ******************************************************************************/ + +acpi_status +acpi_ns_detach_data(struct acpi_namespace_node * node, + acpi_object_handler handler) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *prev_obj_desc; + + prev_obj_desc = NULL; + obj_desc = node->object; + while (obj_desc) { + if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && + (obj_desc->data.handler == handler)) { + if (prev_obj_desc) { + prev_obj_desc->common.next_object = + obj_desc->common.next_object; + } else { + node->object = obj_desc->common.next_object; + } + + acpi_ut_remove_reference(obj_desc); + return (AE_OK); + } + + prev_obj_desc = obj_desc; + obj_desc = obj_desc->common.next_object; + } + + return (AE_NOT_FOUND); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_attached_data + * + * PARAMETERS: Node - Namespace node + * Handler - Handler associated with the data + * Data - Where the data is returned + * + * RETURN: Status + * + * DESCRIPTION: Low level interface to obtain data previously associated with + * a namespace node. + * + ******************************************************************************/ + +acpi_status +acpi_ns_get_attached_data(struct acpi_namespace_node * node, + acpi_object_handler handler, void **data) +{ + union acpi_operand_object *obj_desc; + + obj_desc = node->object; + while (obj_desc) { + if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && + (obj_desc->data.handler == handler)) { + *data = obj_desc->data.pointer; + return (AE_OK); + } + + obj_desc = obj_desc->common.next_object; + } + + return (AE_NOT_FOUND); +} diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c new file mode 100644 index 000000000000..bcfcf427c909 --- /dev/null +++ b/drivers/acpi/acpica/nsparse.c @@ -0,0 +1,204 @@ +/****************************************************************************** + * + * Module Name: nsparse - namespace interface to AML parser + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsparse") + +/******************************************************************************* + * + * FUNCTION: ns_one_complete_parse + * + * PARAMETERS: pass_number - 1 or 2 + * table_desc - The table to be parsed. + * + * RETURN: Status + * + * DESCRIPTION: Perform one complete parse of an ACPI/AML table. + * + ******************************************************************************/ +acpi_status +acpi_ns_one_complete_parse(u32 pass_number, + u32 table_index, + struct acpi_namespace_node *start_node) +{ + union acpi_parse_object *parse_root; + acpi_status status; + u32 aml_length; + u8 *aml_start; + struct acpi_walk_state *walk_state; + struct acpi_table_header *table; + acpi_owner_id owner_id; + + ACPI_FUNCTION_TRACE(ns_one_complete_parse); + + status = acpi_tb_get_owner_id(table_index, &owner_id); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Create and init a Root Node */ + + parse_root = acpi_ps_create_scope_op(); + if (!parse_root) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Create and initialize a new walk state */ + + walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL); + if (!walk_state) { + acpi_ps_free_op(parse_root); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + acpi_ps_free_op(parse_root); + return_ACPI_STATUS(status); + } + + /* Table must consist of at least a complete header */ + + if (table->length < sizeof(struct acpi_table_header)) { + status = AE_BAD_HEADER; + } else { + aml_start = (u8 *) table + sizeof(struct acpi_table_header); + aml_length = table->length - sizeof(struct acpi_table_header); + status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, + aml_start, aml_length, NULL, + (u8) pass_number); + } + + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } + + /* start_node is the default location to load the table */ + + if (start_node && start_node != acpi_gbl_root_node) { + status = + acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD, + walk_state); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } + } + + /* Parse the AML */ + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %d parse\n", + (unsigned)pass_number)); + status = acpi_ps_parse_aml(walk_state); + + cleanup: + acpi_ps_delete_parse_tree(parse_root); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_parse_table + * + * PARAMETERS: table_desc - An ACPI table descriptor for table to parse + * start_node - Where to enter the table into the namespace + * + * RETURN: Status + * + * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops + * + ******************************************************************************/ + +acpi_status +acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ns_parse_table); + + /* + * AML Parse, pass 1 + * + * In this pass, we load most of the namespace. Control methods + * are not parsed until later. A parse tree is not created. Instead, + * each Parser Op subtree is deleted when it is finished. This saves + * a great deal of memory, and allows a small cache of parse objects + * to service the entire parse. The second pass of the parse then + * performs another complete parse of the AML. + */ + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); + status = + acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index, + start_node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * AML Parse, pass 2 + * + * In this pass, we resolve forward references and other things + * that could not be completed during the first pass. + * Another complete parse of the AML is performed, but the + * overhead of this is compensated for by the fact that the + * parse objects are all cached. + */ + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); + status = + acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index, + start_node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c new file mode 100644 index 000000000000..1e682d03f620 --- /dev/null +++ b/drivers/acpi/acpica/nspredef.c @@ -0,0 +1,1065 @@ +/****************************************************************************** + * + * Module Name: nspredef - Validation of ACPI predefined methods and objects + * $Revision: 1.1 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nspredef") + +/******************************************************************************* + * + * This module validates predefined ACPI objects that appear in the namespace, + * at the time they are evaluated (via acpi_evaluate_object). The purpose of this + * validation is to detect problems with BIOS-exposed predefined ACPI objects + * before the results are returned to the ACPI-related drivers. + * + * There are several areas that are validated: + * + * 1) The number of input arguments as defined by the method/object in the + * ASL is validated against the ACPI specification. + * 2) The type of the return object (if any) is validated against the ACPI + * specification. + * 3) For returned package objects, the count of package elements is + * validated, as well as the type of each package element. Nested + * packages are supported. + * + * For any problems found, a warning message is issued. + * + ******************************************************************************/ +/* Local prototypes */ +static acpi_status +acpi_ns_check_package(char *pathname, + union acpi_operand_object **return_object_ptr, + const union acpi_predefined_info *predefined); + +static acpi_status +acpi_ns_check_package_elements(char *pathname, + union acpi_operand_object **elements, + u8 type1, u32 count1, u8 type2, u32 count2); + +static acpi_status +acpi_ns_check_object_type(char *pathname, + union acpi_operand_object **return_object_ptr, + u32 expected_btypes, u32 package_index); + +static acpi_status +acpi_ns_check_reference(char *pathname, + union acpi_operand_object *return_object); + +static acpi_status +acpi_ns_repair_object(u32 expected_btypes, + u32 package_index, + union acpi_operand_object **return_object_ptr); + +/* + * Names for the types that can be returned by the predefined objects. + * Used for warning messages. Must be in the same order as the ACPI_RTYPEs + */ +static const char *acpi_rtype_names[] = { + "/Integer", + "/String", + "/Buffer", + "/Package", + "/Reference", +}; + +#define ACPI_NOT_PACKAGE ACPI_UINT32_MAX + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_predefined_names + * + * PARAMETERS: Node - Namespace node for the method/object + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status + * + * DESCRIPTION: Check an ACPI name for a match in the predefined name list. + * + ******************************************************************************/ + +acpi_status +acpi_ns_check_predefined_names(struct acpi_namespace_node *node, + u32 user_param_count, + acpi_status return_status, + union acpi_operand_object **return_object_ptr) +{ + union acpi_operand_object *return_object = *return_object_ptr; + acpi_status status = AE_OK; + const union acpi_predefined_info *predefined; + char *pathname; + + /* Match the name for this method/object against the predefined list */ + + predefined = acpi_ns_check_for_predefined_name(node); + + /* Get the full pathname to the object, for use in error messages */ + + pathname = acpi_ns_get_external_pathname(node); + if (!pathname) { + pathname = ACPI_CAST_PTR(char, predefined->info.name); + } + + /* + * Check that the parameter count for this method matches the ASL + * definition. For predefined names, ensure that both the caller and + * the method itself are in accordance with the ACPI specification. + */ + acpi_ns_check_parameter_count(pathname, node, user_param_count, + predefined); + + /* If not a predefined name, we cannot validate the return object */ + + if (!predefined) { + goto exit; + } + + /* If the method failed, we cannot validate the return object */ + + if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { + goto exit; + } + + /* + * Only validate the return value on the first successful evaluation of + * the method. This ensures that any warnings will only be emitted during + * the very first evaluation of the method/object. + */ + if (node->flags & ANOBJ_EVALUATED) { + goto exit; + } + + /* Mark the node as having been successfully evaluated */ + + node->flags |= ANOBJ_EVALUATED; + + /* + * If there is no return value, check if we require a return value for + * this predefined name. Either one return value is expected, or none, + * for both methods and other objects. + * + * Exit now if there is no return object. Warning if one was expected. + */ + if (!return_object) { + if ((predefined->info.expected_btypes) && + (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) { + ACPI_ERROR((AE_INFO, + "%s: Missing expected return value", + pathname)); + + status = AE_AML_NO_RETURN_VALUE; + } + goto exit; + } + + /* + * We have a return value, but if one wasn't expected, just exit, this is + * not a problem + * + * For example, if the "Implicit Return" feature is enabled, methods will + * always return a value + */ + if (!predefined->info.expected_btypes) { + goto exit; + } + + /* + * Check that the type of the return object is what is expected for + * this predefined name + */ + status = acpi_ns_check_object_type(pathname, return_object_ptr, + predefined->info.expected_btypes, + ACPI_NOT_PACKAGE); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* For returned Package objects, check the type of all sub-objects */ + + if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) { + status = + acpi_ns_check_package(pathname, return_object_ptr, + predefined); + } + + exit: + if (pathname != predefined->info.name) { + ACPI_FREE(pathname); + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_parameter_count + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * Node - Namespace node for the method/object + * user_param_count - Number of args passed in by the caller + * Predefined - Pointer to entry in predefined name table + * + * RETURN: None + * + * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a + * predefined name is what is expected (i.e., what is defined in + * the ACPI specification for this predefined name.) + * + ******************************************************************************/ + +void +acpi_ns_check_parameter_count(char *pathname, + struct acpi_namespace_node *node, + u32 user_param_count, + const union acpi_predefined_info *predefined) +{ + u32 param_count; + u32 required_params_current; + u32 required_params_old; + + /* Methods have 0-7 parameters. All other types have zero. */ + + param_count = 0; + if (node->type == ACPI_TYPE_METHOD) { + param_count = node->object->method.param_count; + } + + /* Argument count check for non-predefined methods/objects */ + + if (!predefined) { + /* + * Warning if too few or too many arguments have been passed by the + * caller. An incorrect number of arguments may not cause the method + * to fail. However, the method will fail if there are too few + * arguments and the method attempts to use one of the missing ones. + */ + if (user_param_count < param_count) { + ACPI_WARNING((AE_INFO, + "%s: Insufficient arguments - needs %d, found %d", + pathname, param_count, user_param_count)); + } else if (user_param_count > param_count) { + ACPI_WARNING((AE_INFO, + "%s: Excess arguments - needs %d, found %d", + pathname, param_count, user_param_count)); + } + return; + } + + /* Allow two different legal argument counts (_SCP, etc.) */ + + required_params_current = predefined->info.param_count & 0x0F; + required_params_old = predefined->info.param_count >> 4; + + if (user_param_count != ACPI_UINT32_MAX) { + + /* Validate the user-supplied parameter count */ + + if ((user_param_count != required_params_current) && + (user_param_count != required_params_old)) { + ACPI_WARNING((AE_INFO, + "%s: Parameter count mismatch - caller passed %d, ACPI requires %d", + pathname, user_param_count, + required_params_current)); + } + } + + /* + * Only validate the argument count on the first successful evaluation of + * the method. This ensures that any warnings will only be emitted during + * the very first evaluation of the method/object. + */ + if (node->flags & ANOBJ_EVALUATED) { + return; + } + + /* + * Check that the ASL-defined parameter count is what is expected for + * this predefined name. + */ + if ((param_count != required_params_current) && + (param_count != required_params_old)) { + ACPI_WARNING((AE_INFO, + "%s: Parameter count mismatch - ASL declared %d, ACPI requires %d", + pathname, param_count, required_params_current)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_for_predefined_name + * + * PARAMETERS: Node - Namespace node for the method/object + * + * RETURN: Pointer to entry in predefined table. NULL indicates not found. + * + * DESCRIPTION: Check an object name against the predefined object list. + * + ******************************************************************************/ + +const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct + acpi_namespace_node + *node) +{ + const union acpi_predefined_info *this_name; + + /* Quick check for a predefined name, first character must be underscore */ + + if (node->name.ascii[0] != '_') { + return (NULL); + } + + /* Search info table for a predefined method/object name */ + + this_name = predefined_names; + while (this_name->info.name[0]) { + if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) { + + /* Return pointer to this table entry */ + + return (this_name); + } + + /* + * Skip next entry in the table if this name returns a Package + * (next entry contains the package info) + */ + if (this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) { + this_name++; + } + + this_name++; + } + + return (NULL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * Predefined - Pointer to entry in predefined name table + * + * RETURN: Status + * + * DESCRIPTION: Check a returned package object for the correct count and + * correct type of all sub-objects. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package(char *pathname, + union acpi_operand_object **return_object_ptr, + const union acpi_predefined_info *predefined) +{ + union acpi_operand_object *return_object = *return_object_ptr; + const union acpi_predefined_info *package; + union acpi_operand_object *sub_package; + union acpi_operand_object **elements; + union acpi_operand_object **sub_elements; + acpi_status status; + u32 expected_count; + u32 count; + u32 i; + u32 j; + + ACPI_FUNCTION_NAME(ns_check_package); + + /* The package info for this name is in the next table entry */ + + package = predefined + 1; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "%s Validating return Package of Type %X, Count %X\n", + pathname, package->ret_info.type, + return_object->package.count)); + + /* Extract package count and elements array */ + + elements = return_object->package.elements; + count = return_object->package.count; + + /* The package must have at least one element, else invalid */ + + if (!count) { + ACPI_WARNING((AE_INFO, + "%s: Return Package has no elements (empty)", + pathname)); + + return (AE_AML_OPERAND_VALUE); + } + + /* + * Decode the type of the expected package contents + * + * PTYPE1 packages contain no subpackages + * PTYPE2 packages contain sub-packages + */ + switch (package->ret_info.type) { + case ACPI_PTYPE1_FIXED: + + /* + * The package count is fixed and there are no sub-packages + * + * If package is too small, exit. + * If package is larger than expected, issue warning but continue + */ + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (count < expected_count) { + goto package_too_small; + } else if (count > expected_count) { + ACPI_WARNING((AE_INFO, + "%s: Return Package is larger than needed - " + "found %u, expected %u", pathname, count, + expected_count)); + } + + /* Validate all elements of the returned package */ + + status = acpi_ns_check_package_elements(pathname, elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + package->ret_info. + count2); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE1_VAR: + + /* + * The package count is variable, there are no sub-packages, and all + * elements must be of the same type + */ + for (i = 0; i < count; i++) { + status = acpi_ns_check_object_type(pathname, elements, + package->ret_info. + object_type1, i); + if (ACPI_FAILURE(status)) { + return (status); + } + elements++; + } + break; + + case ACPI_PTYPE1_OPTION: + + /* + * The package count is variable, there are no sub-packages. There are + * a fixed number of required elements, and a variable number of + * optional elements. + * + * Check if package is at least as large as the minimum required + */ + expected_count = package->ret_info3.count; + if (count < expected_count) { + goto package_too_small; + } + + /* Variable number of sub-objects */ + + for (i = 0; i < count; i++) { + if (i < package->ret_info3.count) { + + /* These are the required package elements (0, 1, or 2) */ + + status = + acpi_ns_check_object_type(pathname, + elements, + package-> + ret_info3. + object_type[i], + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } else { + /* These are the optional package elements */ + + status = + acpi_ns_check_object_type(pathname, + elements, + package-> + ret_info3. + tail_object_type, + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } + elements++; + } + break; + + case ACPI_PTYPE2_PKG_COUNT: + + /* First element is the (Integer) count of sub-packages to follow */ + + status = acpi_ns_check_object_type(pathname, elements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Count cannot be larger than the parent package length, but allow it + * to be smaller. The >= accounts for the Integer above. + */ + expected_count = (u32) (*elements)->integer.value; + if (expected_count >= count) { + goto package_too_small; + } + + count = expected_count; + elements++; + + /* Now we can walk the sub-packages */ + + /*lint -fallthrough */ + + case ACPI_PTYPE2: + case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_COUNT: + + /* + * These types all return a single package that consists of a variable + * number of sub-packages + */ + for (i = 0; i < count; i++) { + sub_package = *elements; + sub_elements = sub_package->package.elements; + + /* Each sub-object must be of type Package */ + + status = + acpi_ns_check_object_type(pathname, &sub_package, + ACPI_RTYPE_PACKAGE, i); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Examine the different types of sub-packages */ + + switch (package->ret_info.type) { + case ACPI_PTYPE2: + case ACPI_PTYPE2_PKG_COUNT: + + /* Each subpackage has a fixed number of elements */ + + expected_count = + package->ret_info.count1 + + package->ret_info.count2; + if (sub_package->package.count != + expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + status = + acpi_ns_check_package_elements(pathname, + sub_elements, + package-> + ret_info. + object_type1, + package-> + ret_info. + count1, + package-> + ret_info. + object_type2, + package-> + ret_info. + count2); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_FIXED: + + /* Each sub-package has a fixed length */ + + expected_count = package->ret_info2.count; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + for (j = 0; j < expected_count; j++) { + status = + acpi_ns_check_object_type(pathname, + &sub_elements[j], + package->ret_info2.object_type[j], j); + if (ACPI_FAILURE(status)) { + return (status); + } + } + break; + + case ACPI_PTYPE2_MIN: + + /* Each sub-package has a variable but minimum length */ + + expected_count = package->ret_info.count1; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + status = + acpi_ns_check_package_elements(pathname, + sub_elements, + package-> + ret_info. + object_type1, + sub_package-> + package. + count, 0, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_COUNT: + + /* First element is the (Integer) count of elements to follow */ + + status = + acpi_ns_check_object_type(pathname, + sub_elements, + ACPI_RTYPE_INTEGER, + 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Make sure package is large enough for the Count */ + + expected_count = + (u32) (*sub_elements)->integer.value; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + status = + acpi_ns_check_package_elements(pathname, + (sub_elements + + 1), + package-> + ret_info. + object_type1, + (expected_count + - 1), 0, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + default: + break; + } + + elements++; + } + break; + + default: + + /* Should not get here if predefined info table is correct */ + + ACPI_WARNING((AE_INFO, + "%s: Invalid internal return type in table entry: %X", + pathname, package->ret_info.type)); + + return (AE_AML_INTERNAL); + } + + return (AE_OK); + + package_too_small: + + /* Error exit for the case with an incorrect package count */ + + ACPI_WARNING((AE_INFO, "%s: Return Package is too small - " + "found %u, expected %u", pathname, count, + expected_count)); + + return (AE_AML_OPERAND_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package_elements + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * Elements - Pointer to the package elements array + * Type1 - Object type for first group + * Count1 - Count for first group + * Type2 - Object type for second group + * Count2 - Count for second group + * + * RETURN: Status + * + * DESCRIPTION: Check that all elements of a package are of the correct object + * type. Supports up to two groups of different object types. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package_elements(char *pathname, + union acpi_operand_object **elements, + u8 type1, u32 count1, u8 type2, u32 count2) +{ + union acpi_operand_object **this_element = elements; + acpi_status status; + u32 i; + + /* + * Up to two groups of package elements are supported by the data + * structure. All elements in each group must be of the same type. + * The second group can have a count of zero. + */ + for (i = 0; i < count1; i++) { + status = acpi_ns_check_object_type(pathname, this_element, + type1, i); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + for (i = 0; i < count2; i++) { + status = acpi_ns_check_object_type(pathname, this_element, + type2, (i + count1)); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_object_type + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * expected_btypes - Bitmap of expected return type(s) + * package_index - Index of object within parent package (if + * applicable - ACPI_NOT_PACKAGE otherwise) + * + * RETURN: Status + * + * DESCRIPTION: Check the type of the return object against the expected object + * type(s). Use of Btype allows multiple expected object types. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_object_type(char *pathname, + union acpi_operand_object **return_object_ptr, + u32 expected_btypes, u32 package_index) +{ + union acpi_operand_object *return_object = *return_object_ptr; + acpi_status status = AE_OK; + u32 return_btype; + char type_buffer[48]; /* Room for 5 types */ + u32 this_rtype; + u32 i; + u32 j; + + /* + * If we get a NULL return_object here, it is a NULL package element, + * and this is always an error. + */ + if (!return_object) { + goto type_error_exit; + } + + /* A Namespace node should not get here, but make sure */ + + if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { + ACPI_WARNING((AE_INFO, + "%s: Invalid return type - Found a Namespace node [%4.4s] type %s", + pathname, return_object->node.name.ascii, + acpi_ut_get_type_name(return_object->node.type))); + return (AE_AML_OPERAND_TYPE); + } + + /* + * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type. + * The bitmapped type allows multiple possible return types. + * + * Note, the cases below must handle all of the possible types returned + * from all of the predefined names (including elements of returned + * packages) + */ + switch (ACPI_GET_OBJECT_TYPE(return_object)) { + case ACPI_TYPE_INTEGER: + return_btype = ACPI_RTYPE_INTEGER; + break; + + case ACPI_TYPE_BUFFER: + return_btype = ACPI_RTYPE_BUFFER; + break; + + case ACPI_TYPE_STRING: + return_btype = ACPI_RTYPE_STRING; + break; + + case ACPI_TYPE_PACKAGE: + return_btype = ACPI_RTYPE_PACKAGE; + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + return_btype = ACPI_RTYPE_REFERENCE; + break; + + default: + /* Not one of the supported objects, must be incorrect */ + + goto type_error_exit; + } + + /* Is the object one of the expected types? */ + + if (!(return_btype & expected_btypes)) { + + /* Type mismatch -- attempt repair of the returned object */ + + status = acpi_ns_repair_object(expected_btypes, package_index, + return_object_ptr); + if (ACPI_SUCCESS(status)) { + return (status); + } + goto type_error_exit; + } + + /* For reference objects, check that the reference type is correct */ + + if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_LOCAL_REFERENCE) { + status = acpi_ns_check_reference(pathname, return_object); + } + + return (status); + + type_error_exit: + + /* Create a string with all expected types for this predefined object */ + + j = 1; + type_buffer[0] = 0; + this_rtype = ACPI_RTYPE_INTEGER; + + for (i = 0; i < ACPI_NUM_RTYPES; i++) { + + /* If one of the expected types, concatenate the name of this type */ + + if (expected_btypes & this_rtype) { + ACPI_STRCAT(type_buffer, &acpi_rtype_names[i][j]); + j = 0; /* Use name separator from now on */ + } + this_rtype <<= 1; /* Next Rtype */ + } + + if (package_index == ACPI_NOT_PACKAGE) { + ACPI_WARNING((AE_INFO, + "%s: Return type mismatch - found %s, expected %s", + pathname, + acpi_ut_get_object_type_name(return_object), + type_buffer)); + } else { + ACPI_WARNING((AE_INFO, + "%s: Return Package type mismatch at index %u - " + "found %s, expected %s", pathname, package_index, + acpi_ut_get_object_type_name(return_object), + type_buffer)); + } + + return (AE_AML_OPERAND_TYPE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_reference + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * return_object - Object returned from the evaluation of a + * method or object + * + * RETURN: Status + * + * DESCRIPTION: Check a returned reference object for the correct reference + * type. The only reference type that can be returned from a + * predefined method is a named reference. All others are invalid. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_reference(char *pathname, + union acpi_operand_object *return_object) +{ + + /* + * Check the reference object for the correct reference type (opcode). + * The only type of reference that can be converted to an union acpi_object is + * a reference to a named object (reference class: NAME) + */ + if (return_object->reference.class == ACPI_REFCLASS_NAME) { + return (AE_OK); + } + + ACPI_WARNING((AE_INFO, + "%s: Return type mismatch - unexpected reference object type [%s] %2.2X", + pathname, acpi_ut_get_reference_name(return_object), + return_object->reference.class)); + + return (AE_AML_OPERAND_TYPE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_repair_object + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * package_index - Used to determine if target is in a package + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if repair was successful. + * + * DESCRIPTION: Attempt to repair/convert a return object of a type that was + * not expected. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_repair_object(u32 expected_btypes, + u32 package_index, + union acpi_operand_object **return_object_ptr) +{ + union acpi_operand_object *return_object = *return_object_ptr; + union acpi_operand_object *new_object; + acpi_size length; + + switch (ACPI_GET_OBJECT_TYPE(return_object)) { + case ACPI_TYPE_BUFFER: + + if (!(expected_btypes & ACPI_RTYPE_STRING)) { + return (AE_AML_OPERAND_TYPE); + } + + /* + * Have a Buffer, expected a String, convert. Use a to_string + * conversion, no transform performed on the buffer data. The best + * example of this is the _BIF method, where the string data from + * the battery is often (incorrectly) returned as buffer object(s). + */ + length = 0; + while ((length < return_object->buffer.length) && + (return_object->buffer.pointer[length])) { + length++; + } + + /* Allocate a new string object */ + + new_object = acpi_ut_create_string_object(length); + if (!new_object) { + return (AE_NO_MEMORY); + } + + /* + * Copy the raw buffer data with no transform. String is already NULL + * terminated at Length+1. + */ + ACPI_MEMCPY(new_object->string.pointer, + return_object->buffer.pointer, length); + + /* Install the new return object */ + + acpi_ut_remove_reference(return_object); + *return_object_ptr = new_object; + + /* + * If the object is a package element, we need to: + * 1. Decrement the reference count of the orignal object, it was + * incremented when building the package + * 2. Increment the reference count of the new object, it will be + * decremented when releasing the package + */ + if (package_index != ACPI_NOT_PACKAGE) { + acpi_ut_remove_reference(return_object); + acpi_ut_add_reference(new_object); + } + return (AE_OK); + + default: + break; + } + + return (AE_AML_OPERAND_TYPE); +} diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c new file mode 100644 index 000000000000..a76c731e3ba5 --- /dev/null +++ b/drivers/acpi/acpica/nssearch.c @@ -0,0 +1,415 @@ +/******************************************************************************* + * + * Module Name: nssearch - Namespace search + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nssearch") + +/* Local prototypes */ +static acpi_status +acpi_ns_search_parent_tree(u32 target_name, + struct acpi_namespace_node *node, + acpi_object_type type, + struct acpi_namespace_node **return_node); + +/******************************************************************************* + * + * FUNCTION: acpi_ns_search_one_scope + * + * PARAMETERS: target_name - Ascii ACPI name to search for + * parent_node - Starting node where search will begin + * Type - Object type to match + * return_node - Where the matched Named obj is returned + * + * RETURN: Status + * + * DESCRIPTION: Search a single level of the namespace. Performs a + * simple search of the specified level, and does not add + * entries or search parents. + * + * + * Named object lists are built (and subsequently dumped) in the + * order in which the names are encountered during the namespace load; + * + * All namespace searching is linear in this implementation, but + * could be easily modified to support any improved search + * algorithm. However, the linear search was chosen for simplicity + * and because the trees are small and the other interpreter + * execution overhead is relatively high. + * + * Note: CPU execution analysis has shown that the AML interpreter spends + * a very small percentage of its time searching the namespace. Therefore, + * the linear search seems to be sufficient, as there would seem to be + * little value in improving the search. + * + ******************************************************************************/ + +acpi_status +acpi_ns_search_one_scope(u32 target_name, + struct acpi_namespace_node *parent_node, + acpi_object_type type, + struct acpi_namespace_node **return_node) +{ + struct acpi_namespace_node *node; + + ACPI_FUNCTION_TRACE(ns_search_one_scope); + +#ifdef ACPI_DEBUG_OUTPUT + if (ACPI_LV_NAMES & acpi_dbg_level) { + char *scope_name; + + scope_name = acpi_ns_get_external_pathname(parent_node); + if (scope_name) { + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Searching %s (%p) For [%4.4s] (%s)\n", + scope_name, parent_node, + ACPI_CAST_PTR(char, &target_name), + acpi_ut_get_type_name(type))); + + ACPI_FREE(scope_name); + } + } +#endif + + /* + * Search for name at this namespace level, which is to say that we + * must search for the name among the children of this object + */ + node = parent_node->child; + while (node) { + + /* Check for match against the name */ + + if (node->name.integer == target_name) { + + /* Resolve a control method alias if any */ + + if (acpi_ns_get_type(node) == + ACPI_TYPE_LOCAL_METHOD_ALIAS) { + node = + ACPI_CAST_PTR(struct acpi_namespace_node, + node->object); + } + + /* Found matching entry */ + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n", + ACPI_CAST_PTR(char, &target_name), + acpi_ut_get_type_name(node->type), + node, + acpi_ut_get_node_name(parent_node), + parent_node)); + + *return_node = node; + return_ACPI_STATUS(AE_OK); + } + + /* + * The last entry in the list points back to the parent, + * so a flag is used to indicate the end-of-list + */ + if (node->flags & ANOBJ_END_OF_PEER_LIST) { + + /* Searched entire list, we are done */ + + break; + } + + /* Didn't match name, move on to the next peer object */ + + node = node->peer; + } + + /* Searched entire namespace level, not found */ + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n", + ACPI_CAST_PTR(char, &target_name), + acpi_ut_get_type_name(type), + acpi_ut_get_node_name(parent_node), parent_node, + parent_node->child)); + + return_ACPI_STATUS(AE_NOT_FOUND); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_search_parent_tree + * + * PARAMETERS: target_name - Ascii ACPI name to search for + * Node - Starting node where search will begin + * Type - Object type to match + * return_node - Where the matched Node is returned + * + * RETURN: Status + * + * DESCRIPTION: Called when a name has not been found in the current namespace + * level. Before adding it or giving up, ACPI scope rules require + * searching enclosing scopes in cases identified by acpi_ns_local(). + * + * "A name is located by finding the matching name in the current + * name space, and then in the parent name space. If the parent + * name space does not contain the name, the search continues + * recursively until either the name is found or the name space + * does not have a parent (the root of the name space). This + * indicates that the name is not found" (From ACPI Specification, + * section 5.3) + * + ******************************************************************************/ + +static acpi_status +acpi_ns_search_parent_tree(u32 target_name, + struct acpi_namespace_node *node, + acpi_object_type type, + struct acpi_namespace_node **return_node) +{ + acpi_status status; + struct acpi_namespace_node *parent_node; + + ACPI_FUNCTION_TRACE(ns_search_parent_tree); + + parent_node = acpi_ns_get_parent_node(node); + + /* + * If there is no parent (i.e., we are at the root) or type is "local", + * we won't be searching the parent tree. + */ + if (!parent_node) { + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "[%4.4s] has no parent\n", + ACPI_CAST_PTR(char, &target_name))); + return_ACPI_STATUS(AE_NOT_FOUND); + } + + if (acpi_ns_local(type)) { + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "[%4.4s] type [%s] must be local to this scope (no parent search)\n", + ACPI_CAST_PTR(char, &target_name), + acpi_ut_get_type_name(type))); + return_ACPI_STATUS(AE_NOT_FOUND); + } + + /* Search the parent tree */ + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Searching parent [%4.4s] for [%4.4s]\n", + acpi_ut_get_node_name(parent_node), + ACPI_CAST_PTR(char, &target_name))); + + /* + * Search parents until target is found or we have backed up to the root + */ + while (parent_node) { + /* + * Search parent scope. Use TYPE_ANY because we don't care about the + * object type at this point, we only care about the existence of + * the actual name we are searching for. Typechecking comes later. + */ + status = + acpi_ns_search_one_scope(target_name, parent_node, + ACPI_TYPE_ANY, return_node); + if (ACPI_SUCCESS(status)) { + return_ACPI_STATUS(status); + } + + /* Not found here, go up another level (until we reach the root) */ + + parent_node = acpi_ns_get_parent_node(parent_node); + } + + /* Not found in parent tree */ + + return_ACPI_STATUS(AE_NOT_FOUND); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_search_and_enter + * + * PARAMETERS: target_name - Ascii ACPI name to search for (4 chars) + * walk_state - Current state of the walk + * Node - Starting node where search will begin + * interpreter_mode - Add names only in ACPI_MODE_LOAD_PASS_x. + * Otherwise,search only. + * Type - Object type to match + * Flags - Flags describing the search restrictions + * return_node - Where the Node is returned + * + * RETURN: Status + * + * DESCRIPTION: Search for a name segment in a single namespace level, + * optionally adding it if it is not found. If the passed + * Type is not Any and the type previously stored in the + * entry was Any (i.e. unknown), update the stored type. + * + * In ACPI_IMODE_EXECUTE, search only. + * In other modes, search and add if not found. + * + ******************************************************************************/ + +acpi_status +acpi_ns_search_and_enter(u32 target_name, + struct acpi_walk_state *walk_state, + struct acpi_namespace_node *node, + acpi_interpreter_mode interpreter_mode, + acpi_object_type type, + u32 flags, struct acpi_namespace_node **return_node) +{ + acpi_status status; + struct acpi_namespace_node *new_node; + + ACPI_FUNCTION_TRACE(ns_search_and_enter); + + /* Parameter validation */ + + if (!node || !target_name || !return_node) { + ACPI_ERROR((AE_INFO, + "Null parameter: Node %p Name %X ReturnNode %p", + node, target_name, return_node)); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Name must consist of valid ACPI characters. We will repair the name if + * necessary because we don't want to abort because of this, but we want + * all namespace names to be printable. A warning message is appropriate. + * + * This issue came up because there are in fact machines that exhibit + * this problem, and we want to be able to enable ACPI support for them, + * even though there are a few bad names. + */ + if (!acpi_ut_valid_acpi_name(target_name)) { + target_name = + acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name)); + + /* Report warning only if in strict mode or debug mode */ + + if (!acpi_gbl_enable_interpreter_slack) { + ACPI_WARNING((AE_INFO, + "Found bad character(s) in name, repaired: [%4.4s]\n", + ACPI_CAST_PTR(char, &target_name))); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Found bad character(s) in name, repaired: [%4.4s]\n", + ACPI_CAST_PTR(char, &target_name))); + } + } + + /* Try to find the name in the namespace level specified by the caller */ + + *return_node = ACPI_ENTRY_NOT_FOUND; + status = acpi_ns_search_one_scope(target_name, node, type, return_node); + if (status != AE_NOT_FOUND) { + /* + * If we found it AND the request specifies that a find is an error, + * return the error + */ + if ((status == AE_OK) && (flags & ACPI_NS_ERROR_IF_FOUND)) { + status = AE_ALREADY_EXISTS; + } + + /* Either found it or there was an error: finished either way */ + + return_ACPI_STATUS(status); + } + + /* + * The name was not found. If we are NOT performing the first pass + * (name entry) of loading the namespace, search the parent tree (all the + * way to the root if necessary.) We don't want to perform the parent + * search when the namespace is actually being loaded. We want to perform + * the search when namespace references are being resolved (load pass 2) + * and during the execution phase. + */ + if ((interpreter_mode != ACPI_IMODE_LOAD_PASS1) && + (flags & ACPI_NS_SEARCH_PARENT)) { + /* + * Not found at this level - search parent tree according to the + * ACPI specification + */ + status = + acpi_ns_search_parent_tree(target_name, node, type, + return_node); + if (ACPI_SUCCESS(status)) { + return_ACPI_STATUS(status); + } + } + + /* In execute mode, just search, never add names. Exit now */ + + if (interpreter_mode == ACPI_IMODE_EXECUTE) { + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "%4.4s Not found in %p [Not adding]\n", + ACPI_CAST_PTR(char, &target_name), node)); + + return_ACPI_STATUS(AE_NOT_FOUND); + } + + /* Create the new named object */ + + new_node = acpi_ns_create_node(target_name); + if (!new_node) { + return_ACPI_STATUS(AE_NO_MEMORY); + } +#ifdef ACPI_ASL_COMPILER + /* + * Node is an object defined by an External() statement + */ + if (flags & ACPI_NS_EXTERNAL) { + new_node->flags |= ANOBJ_IS_EXTERNAL; + } +#endif + + if (flags & ACPI_NS_TEMPORARY) { + new_node->flags |= ANOBJ_TEMPORARY; + } + + /* Install the new object into the parent's list of children */ + + acpi_ns_install_node(walk_state, node, new_node, type); + *return_node = new_node; + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c new file mode 100644 index 000000000000..a443d2805d2c --- /dev/null +++ b/drivers/acpi/acpica/nsutils.c @@ -0,0 +1,997 @@ +/****************************************************************************** + * + * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing + * parents and siblings and Scope manipulation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsutils") + +/* Local prototypes */ +static u8 acpi_ns_valid_path_separator(char sep); + +#ifdef ACPI_OBSOLETE_FUNCTIONS +acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ns_report_error + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * internal_name - Name or path of the namespace node + * lookup_status - Exception code from NS lookup + * + * RETURN: None + * + * DESCRIPTION: Print warning message with full pathname + * + ******************************************************************************/ + +void +acpi_ns_report_error(const char *module_name, + u32 line_number, + const char *internal_name, acpi_status lookup_status) +{ + acpi_status status; + u32 bad_name; + char *name = NULL; + + acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); + + if (lookup_status == AE_BAD_CHARACTER) { + + /* There is a non-ascii character in the name */ + + ACPI_MOVE_32_TO_32(&bad_name, internal_name); + acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); + } else { + /* Convert path to external format */ + + status = acpi_ns_externalize_name(ACPI_UINT32_MAX, + internal_name, NULL, &name); + + /* Print target name */ + + if (ACPI_SUCCESS(status)) { + acpi_os_printf("[%s]", name); + } else { + acpi_os_printf("[COULD NOT EXTERNALIZE NAME]"); + } + + if (name) { + ACPI_FREE(name); + } + } + + acpi_os_printf(" Namespace lookup failure, %s\n", + acpi_format_exception(lookup_status)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_report_method_error + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * Message - Error message to use on failure + * prefix_node - Prefix relative to the path + * Path - Path to the node (optional) + * method_status - Execution status + * + * RETURN: None + * + * DESCRIPTION: Print warning message with full pathname + * + ******************************************************************************/ + +void +acpi_ns_report_method_error(const char *module_name, + u32 line_number, + const char *message, + struct acpi_namespace_node *prefix_node, + const char *path, acpi_status method_status) +{ + acpi_status status; + struct acpi_namespace_node *node = prefix_node; + + acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); + + if (path) { + status = + acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, + &node); + if (ACPI_FAILURE(status)) { + acpi_os_printf("[Could not get node by pathname]"); + } + } + + acpi_ns_print_node_pathname(node, message); + acpi_os_printf(", %s\n", acpi_format_exception(method_status)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_print_node_pathname + * + * PARAMETERS: Node - Object + * Message - Prefix message + * + * DESCRIPTION: Print an object's full namespace pathname + * Manages allocation/freeing of a pathname buffer + * + ******************************************************************************/ + +void +acpi_ns_print_node_pathname(struct acpi_namespace_node *node, + const char *message) +{ + struct acpi_buffer buffer; + acpi_status status; + + if (!node) { + acpi_os_printf("[NULL NAME]"); + return; + } + + /* Convert handle to full pathname and print it (with supplied message) */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + + status = acpi_ns_handle_to_pathname(node, &buffer); + if (ACPI_SUCCESS(status)) { + if (message) { + acpi_os_printf("%s ", message); + } + + acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node); + ACPI_FREE(buffer.pointer); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_valid_root_prefix + * + * PARAMETERS: Prefix - Character to be checked + * + * RETURN: TRUE if a valid prefix + * + * DESCRIPTION: Check if a character is a valid ACPI Root prefix + * + ******************************************************************************/ + +u8 acpi_ns_valid_root_prefix(char prefix) +{ + + return ((u8) (prefix == '\\')); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_valid_path_separator + * + * PARAMETERS: Sep - Character to be checked + * + * RETURN: TRUE if a valid path separator + * + * DESCRIPTION: Check if a character is a valid ACPI path separator + * + ******************************************************************************/ + +static u8 acpi_ns_valid_path_separator(char sep) +{ + + return ((u8) (sep == '.')); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_type + * + * PARAMETERS: Node - Parent Node to be examined + * + * RETURN: Type field from Node whose handle is passed + * + * DESCRIPTION: Return the type of a Namespace node + * + ******************************************************************************/ + +acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) +{ + ACPI_FUNCTION_TRACE(ns_get_type); + + if (!node) { + ACPI_WARNING((AE_INFO, "Null Node parameter")); + return_UINT32(ACPI_TYPE_ANY); + } + + return_UINT32((acpi_object_type) node->type); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_local + * + * PARAMETERS: Type - A namespace object type + * + * RETURN: LOCAL if names must be found locally in objects of the + * passed type, 0 if enclosing scopes should be searched + * + * DESCRIPTION: Returns scope rule for the given object type. + * + ******************************************************************************/ + +u32 acpi_ns_local(acpi_object_type type) +{ + ACPI_FUNCTION_TRACE(ns_local); + + if (!acpi_ut_valid_object_type(type)) { + + /* Type code out of range */ + + ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); + return_UINT32(ACPI_NS_NORMAL); + } + + return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_internal_name_length + * + * PARAMETERS: Info - Info struct initialized with the + * external name pointer. + * + * RETURN: None + * + * DESCRIPTION: Calculate the length of the internal (AML) namestring + * corresponding to the external (ASL) namestring. + * + ******************************************************************************/ + +void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) +{ + const char *next_external_char; + u32 i; + + ACPI_FUNCTION_ENTRY(); + + next_external_char = info->external_name; + info->num_carats = 0; + info->num_segments = 0; + info->fully_qualified = FALSE; + + /* + * For the internal name, the required length is 4 bytes per segment, plus + * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null + * (which is not really needed, but no there's harm in putting it there) + * + * strlen() + 1 covers the first name_seg, which has no path separator + */ + if (acpi_ns_valid_root_prefix(*next_external_char)) { + info->fully_qualified = TRUE; + next_external_char++; + + /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */ + + while (acpi_ns_valid_root_prefix(*next_external_char)) { + next_external_char++; + } + } else { + /* + * Handle Carat prefixes + */ + while (*next_external_char == '^') { + info->num_carats++; + next_external_char++; + } + } + + /* + * Determine the number of ACPI name "segments" by counting the number of + * path separators within the string. Start with one segment since the + * segment count is [(# separators) + 1], and zero separators is ok. + */ + if (*next_external_char) { + info->num_segments = 1; + for (i = 0; next_external_char[i]; i++) { + if (acpi_ns_valid_path_separator(next_external_char[i])) { + info->num_segments++; + } + } + } + + info->length = (ACPI_NAME_SIZE * info->num_segments) + + 4 + info->num_carats; + + info->next_external_char = next_external_char; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_build_internal_name + * + * PARAMETERS: Info - Info struct fully initialized + * + * RETURN: Status + * + * DESCRIPTION: Construct the internal (AML) namestring + * corresponding to the external (ASL) namestring. + * + ******************************************************************************/ + +acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) +{ + u32 num_segments = info->num_segments; + char *internal_name = info->internal_name; + const char *external_name = info->next_external_char; + char *result = NULL; + u32 i; + + ACPI_FUNCTION_TRACE(ns_build_internal_name); + + /* Setup the correct prefixes, counts, and pointers */ + + if (info->fully_qualified) { + internal_name[0] = '\\'; + + if (num_segments <= 1) { + result = &internal_name[1]; + } else if (num_segments == 2) { + internal_name[1] = AML_DUAL_NAME_PREFIX; + result = &internal_name[2]; + } else { + internal_name[1] = AML_MULTI_NAME_PREFIX_OP; + internal_name[2] = (char)num_segments; + result = &internal_name[3]; + } + } else { + /* + * Not fully qualified. + * Handle Carats first, then append the name segments + */ + i = 0; + if (info->num_carats) { + for (i = 0; i < info->num_carats; i++) { + internal_name[i] = '^'; + } + } + + if (num_segments <= 1) { + result = &internal_name[i]; + } else if (num_segments == 2) { + internal_name[i] = AML_DUAL_NAME_PREFIX; + result = &internal_name[(acpi_size) i + 1]; + } else { + internal_name[i] = AML_MULTI_NAME_PREFIX_OP; + internal_name[(acpi_size) i + 1] = (char)num_segments; + result = &internal_name[(acpi_size) i + 2]; + } + } + + /* Build the name (minus path separators) */ + + for (; num_segments; num_segments--) { + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (acpi_ns_valid_path_separator(*external_name) || + (*external_name == 0)) { + + /* Pad the segment with underscore(s) if segment is short */ + + result[i] = '_'; + } else { + /* Convert the character to uppercase and save it */ + + result[i] = + (char)ACPI_TOUPPER((int)*external_name); + external_name++; + } + } + + /* Now we must have a path separator, or the pathname is bad */ + + if (!acpi_ns_valid_path_separator(*external_name) && + (*external_name != 0)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Move on the next segment */ + + external_name++; + result += ACPI_NAME_SIZE; + } + + /* Terminate the string */ + + *result = 0; + + if (info->fully_qualified) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Returning [%p] (abs) \"\\%s\"\n", + internal_name, internal_name)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n", + internal_name, internal_name)); + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_internalize_name + * + * PARAMETERS: *external_name - External representation of name + * **Converted Name - Where to return the resulting + * internal represention of the name + * + * RETURN: Status + * + * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") + * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) + * + *******************************************************************************/ + +acpi_status +acpi_ns_internalize_name(const char *external_name, char **converted_name) +{ + char *internal_name; + struct acpi_namestring_info info; + acpi_status status; + + ACPI_FUNCTION_TRACE(ns_internalize_name); + + if ((!external_name) || (*external_name == 0) || (!converted_name)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the length of the new internal name */ + + info.external_name = external_name; + acpi_ns_get_internal_name_length(&info); + + /* We need a segment to store the internal name */ + + internal_name = ACPI_ALLOCATE_ZEROED(info.length); + if (!internal_name) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Build the name */ + + info.internal_name = internal_name; + status = acpi_ns_build_internal_name(&info); + if (ACPI_FAILURE(status)) { + ACPI_FREE(internal_name); + return_ACPI_STATUS(status); + } + + *converted_name = internal_name; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_externalize_name + * + * PARAMETERS: internal_name_length - Lenth of the internal name below + * internal_name - Internal representation of name + * converted_name_length - Where the length is returned + * converted_name - Where the resulting external name + * is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) + * to its external (printable) form (e.g. "\_PR_.CPU0") + * + ******************************************************************************/ + +acpi_status +acpi_ns_externalize_name(u32 internal_name_length, + const char *internal_name, + u32 * converted_name_length, char **converted_name) +{ + u32 names_index = 0; + u32 num_segments = 0; + u32 required_length; + u32 prefix_length = 0; + u32 i = 0; + u32 j = 0; + + ACPI_FUNCTION_TRACE(ns_externalize_name); + + if (!internal_name_length || !internal_name || !converted_name) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Check for a prefix (one '\' | one or more '^'). + */ + switch (internal_name[0]) { + case '\\': + prefix_length = 1; + break; + + case '^': + for (i = 0; i < internal_name_length; i++) { + if (internal_name[i] == '^') { + prefix_length = i + 1; + } else { + break; + } + } + + if (i == internal_name_length) { + prefix_length = i; + } + + break; + + default: + break; + } + + /* + * Check for object names. Note that there could be 0-255 of these + * 4-byte elements. + */ + if (prefix_length < internal_name_length) { + switch (internal_name[prefix_length]) { + case AML_MULTI_NAME_PREFIX_OP: + + /* 4-byte names */ + + names_index = prefix_length + 2; + num_segments = (u8) + internal_name[(acpi_size) prefix_length + 1]; + break; + + case AML_DUAL_NAME_PREFIX: + + /* Two 4-byte names */ + + names_index = prefix_length + 1; + num_segments = 2; + break; + + case 0: + + /* null_name */ + + names_index = 0; + num_segments = 0; + break; + + default: + + /* one 4-byte name */ + + names_index = prefix_length; + num_segments = 1; + break; + } + } + + /* + * Calculate the length of converted_name, which equals the length + * of the prefix, length of all object names, length of any required + * punctuation ('.') between object names, plus the NULL terminator. + */ + required_length = prefix_length + (4 * num_segments) + + ((num_segments > 0) ? (num_segments - 1) : 0) + 1; + + /* + * Check to see if we're still in bounds. If not, there's a problem + * with internal_name (invalid format). + */ + if (required_length > internal_name_length) { + ACPI_ERROR((AE_INFO, "Invalid internal name")); + return_ACPI_STATUS(AE_BAD_PATHNAME); + } + + /* + * Build converted_name + */ + *converted_name = ACPI_ALLOCATE_ZEROED(required_length); + if (!(*converted_name)) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + j = 0; + + for (i = 0; i < prefix_length; i++) { + (*converted_name)[j++] = internal_name[i]; + } + + if (num_segments > 0) { + for (i = 0; i < num_segments; i++) { + if (i > 0) { + (*converted_name)[j++] = '.'; + } + + (*converted_name)[j++] = internal_name[names_index++]; + (*converted_name)[j++] = internal_name[names_index++]; + (*converted_name)[j++] = internal_name[names_index++]; + (*converted_name)[j++] = internal_name[names_index++]; + } + } + + if (converted_name_length) { + *converted_name_length = (u32) required_length; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_map_handle_to_node + * + * PARAMETERS: Handle - Handle to be converted to an Node + * + * RETURN: A Name table entry pointer + * + * DESCRIPTION: Convert a namespace handle to a real Node + * + * Note: Real integer handles would allow for more verification + * and keep all pointers within this subsystem - however this introduces + * more (and perhaps unnecessary) overhead. + * + ******************************************************************************/ + +struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) +{ + + ACPI_FUNCTION_ENTRY(); + + /* + * Simple implementation + */ + if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { + return (acpi_gbl_root_node); + } + + /* We can at least attempt to verify the handle */ + + if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) { + return (NULL); + } + + return (ACPI_CAST_PTR(struct acpi_namespace_node, handle)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_entry_to_handle + * + * PARAMETERS: Node - Node to be converted to a Handle + * + * RETURN: A user handle + * + * DESCRIPTION: Convert a real Node to a namespace handle + * + ******************************************************************************/ + +acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node) +{ + + /* + * Simple implementation for now; + */ + return ((acpi_handle) node); + +/* Example future implementation --------------------- + + if (!Node) + { + return (NULL); + } + + if (Node == acpi_gbl_root_node) + { + return (ACPI_ROOT_OBJECT); + } + + return ((acpi_handle) Node); +------------------------------------------------------*/ +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: free memory allocated for namespace and ACPI table storage. + * + ******************************************************************************/ + +void acpi_ns_terminate(void) +{ + union acpi_operand_object *obj_desc; + + ACPI_FUNCTION_TRACE(ns_terminate); + + /* + * 1) Free the entire namespace -- all nodes and objects + * + * Delete all object descriptors attached to namepsace nodes + */ + acpi_ns_delete_namespace_subtree(acpi_gbl_root_node); + + /* Detach any objects attached to the root */ + + obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node); + if (obj_desc) { + acpi_ns_detach_object(acpi_gbl_root_node); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_opens_scope + * + * PARAMETERS: Type - A valid namespace type + * + * RETURN: NEWSCOPE if the passed type "opens a name scope" according + * to the ACPI specification, else 0 + * + ******************************************************************************/ + +u32 acpi_ns_opens_scope(acpi_object_type type) +{ + ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); + + if (!acpi_ut_valid_object_type(type)) { + + /* type code out of range */ + + ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); + return_UINT32(ACPI_NS_NORMAL); + } + + return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_node + * + * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The + * \ (backslash) and ^ (carat) prefixes, and the + * . (period) to separate segments are supported. + * prefix_node - Root of subtree to be searched, or NS_ALL for the + * root of the name space. If Name is fully + * qualified (first s8 is '\'), the passed value + * of Scope will not be accessed. + * Flags - Used to indicate whether to perform upsearch or + * not. + * return_node - Where the Node is returned + * + * DESCRIPTION: Look up a name relative to a given scope and return the + * corresponding Node. NOTE: Scope can be null. + * + * MUTEX: Locks namespace + * + ******************************************************************************/ + +acpi_status +acpi_ns_get_node(struct acpi_namespace_node *prefix_node, + const char *pathname, + u32 flags, struct acpi_namespace_node **return_node) +{ + union acpi_generic_state scope_info; + acpi_status status; + char *internal_path; + + ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname); + + if (!pathname) { + *return_node = prefix_node; + if (!prefix_node) { + *return_node = acpi_gbl_root_node; + } + return_ACPI_STATUS(AE_OK); + } + + /* Convert path to internal representation */ + + status = acpi_ns_internalize_name(pathname, &internal_path); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Must lock namespace during lookup */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Setup lookup scope (search starting point) */ + + scope_info.scope.node = prefix_node; + + /* Lookup the name in the namespace */ + + status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, + (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, + return_node); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n", + pathname, acpi_format_exception(status))); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + + cleanup: + ACPI_FREE(internal_path); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_parent_node + * + * PARAMETERS: Node - Current table entry + * + * RETURN: Parent entry of the given entry + * + * DESCRIPTION: Obtain the parent entry for a given entry in the namespace. + * + ******************************************************************************/ + +struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node + *node) +{ + ACPI_FUNCTION_ENTRY(); + + if (!node) { + return (NULL); + } + + /* + * Walk to the end of this peer list. The last entry is marked with a flag + * and the peer pointer is really a pointer back to the parent. This saves + * putting a parent back pointer in each and every named object! + */ + while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) { + node = node->peer; + } + + return (node->peer); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_next_valid_node + * + * PARAMETERS: Node - Current table entry + * + * RETURN: Next valid Node in the linked node list. NULL if no more valid + * nodes. + * + * DESCRIPTION: Find the next valid node within a name table. + * Useful for implementing NULL-end-of-list loops. + * + ******************************************************************************/ + +struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct + acpi_namespace_node + *node) +{ + + /* If we are at the end of this peer list, return NULL */ + + if (node->flags & ANOBJ_END_OF_PEER_LIST) { + return NULL; + } + + /* Otherwise just return the next peer */ + + return (node->peer); +} + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: acpi_ns_find_parent_name + * + * PARAMETERS: *child_node - Named Obj whose name is to be found + * + * RETURN: The ACPI name + * + * DESCRIPTION: Search for the given obj in its parent scope and return the + * name segment, or "????" if the parent name can't be found + * (which "should not happen"). + * + ******************************************************************************/ + +acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node) +{ + struct acpi_namespace_node *parent_node; + + ACPI_FUNCTION_TRACE(ns_find_parent_name); + + if (child_node) { + + /* Valid entry. Get the parent Node */ + + parent_node = acpi_ns_get_parent_node(child_node); + if (parent_node) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Parent of %p [%4.4s] is %p [%4.4s]\n", + child_node, + acpi_ut_get_node_name(child_node), + parent_node, + acpi_ut_get_node_name(parent_node))); + + if (parent_node->name.integer) { + return_VALUE((acpi_name) parent_node->name. + integer); + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Unable to find parent of %p (%4.4s)\n", + child_node, + acpi_ut_get_node_name(child_node))); + } + + return_VALUE(ACPI_UNKNOWN_NAME); +} +#endif diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c new file mode 100644 index 000000000000..71b83e9807da --- /dev/null +++ b/drivers/acpi/acpica/nswalk.c @@ -0,0 +1,296 @@ +/****************************************************************************** + * + * Module Name: nswalk - Functions for walking the ACPI namespace + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nswalk") + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_next_node + * + * PARAMETERS: Type - Type of node to be searched for + * parent_node - Parent node whose children we are + * getting + * child_node - Previous child that was found. + * The NEXT child will be returned + * + * RETURN: struct acpi_namespace_node - Pointer to the NEXT child or NULL if + * none is found. + * + * DESCRIPTION: Return the next peer node within the namespace. If Handle + * is valid, Scope is ignored. Otherwise, the first node + * within Scope is returned. + * + ******************************************************************************/ +struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct acpi_namespace_node + *parent_node, struct acpi_namespace_node + *child_node) +{ + struct acpi_namespace_node *next_node = NULL; + + ACPI_FUNCTION_ENTRY(); + + if (!child_node) { + + /* It's really the parent's _scope_ that we want */ + + next_node = parent_node->child; + } + + else { + /* Start search at the NEXT node */ + + next_node = acpi_ns_get_next_valid_node(child_node); + } + + /* If any type is OK, we are done */ + + if (type == ACPI_TYPE_ANY) { + + /* next_node is NULL if we are at the end-of-list */ + + return (next_node); + } + + /* Must search for the node -- but within this scope only */ + + while (next_node) { + + /* If type matches, we are done */ + + if (next_node->type == type) { + return (next_node); + } + + /* Otherwise, move on to the next node */ + + next_node = acpi_ns_get_next_valid_node(next_node); + } + + /* Not found */ + + return (NULL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_walk_namespace + * + * PARAMETERS: Type - acpi_object_type to search for + * start_node - Handle in namespace where search begins + * max_depth - Depth to which search is to reach + * Flags - Whether to unlock the NS before invoking + * the callback routine + * user_function - Called when an object of "Type" is found + * Context - Passed to user function + * return_value - from the user_function if terminated early. + * Otherwise, returns NULL. + * RETURNS: Status + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the node specified by start_handle. + * The user_function is called whenever a node that matches + * the type parameter is found. If the user function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * The point of this procedure is to provide a generic namespace + * walk routine that can be called from multiple places to + * provide multiple services; the User Function can be tailored + * to each task, whether it is a print function, a compare + * function, etc. + * + ******************************************************************************/ + +acpi_status +acpi_ns_walk_namespace(acpi_object_type type, + acpi_handle start_node, + u32 max_depth, + u32 flags, + acpi_walk_callback user_function, + void *context, void **return_value) +{ + acpi_status status; + acpi_status mutex_status; + struct acpi_namespace_node *child_node; + struct acpi_namespace_node *parent_node; + acpi_object_type child_type; + u32 level; + + ACPI_FUNCTION_TRACE(ns_walk_namespace); + + /* Special case for the namespace Root Node */ + + if (start_node == ACPI_ROOT_OBJECT) { + start_node = acpi_gbl_root_node; + } + + /* Null child means "get first node" */ + + parent_node = start_node; + child_node = NULL; + child_type = ACPI_TYPE_ANY; + level = 1; + + /* + * Traverse the tree of nodes until we bubble back up to where we + * started. When Level is zero, the loop is done because we have + * bubbled up to (and passed) the original parent handle (start_entry) + */ + while (level > 0) { + + /* Get the next node in this scope. Null if not found */ + + status = AE_OK; + child_node = + acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, + child_node); + if (child_node) { + + /* Found next child, get the type if we are not searching for ANY */ + + if (type != ACPI_TYPE_ANY) { + child_type = child_node->type; + } + + /* + * Ignore all temporary namespace nodes (created during control + * method execution) unless told otherwise. These temporary nodes + * can cause a race condition because they can be deleted during the + * execution of the user function (if the namespace is unlocked before + * invocation of the user function.) Only the debugger namespace dump + * will examine the temporary nodes. + */ + if ((child_node->flags & ANOBJ_TEMPORARY) && + !(flags & ACPI_NS_WALK_TEMP_NODES)) { + status = AE_CTRL_DEPTH; + } + + /* Type must match requested type */ + + else if (child_type == type) { + /* + * Found a matching node, invoke the user callback function. + * Unlock the namespace if flag is set. + */ + if (flags & ACPI_NS_WALK_UNLOCK) { + mutex_status = + acpi_ut_release_mutex + (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(mutex_status)) { + return_ACPI_STATUS + (mutex_status); + } + } + + status = + user_function(child_node, level, context, + return_value); + + if (flags & ACPI_NS_WALK_UNLOCK) { + mutex_status = + acpi_ut_acquire_mutex + (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(mutex_status)) { + return_ACPI_STATUS + (mutex_status); + } + } + + switch (status) { + case AE_OK: + case AE_CTRL_DEPTH: + + /* Just keep going */ + break; + + case AE_CTRL_TERMINATE: + + /* Exit now, with OK status */ + + return_ACPI_STATUS(AE_OK); + + default: + + /* All others are valid exceptions */ + + return_ACPI_STATUS(status); + } + } + + /* + * Depth first search: Attempt to go down another level in the + * namespace if we are allowed to. Don't go any further if we have + * reached the caller specified maximum depth or if the user + * function has specified that the maximum depth has been reached. + */ + if ((level < max_depth) && (status != AE_CTRL_DEPTH)) { + if (acpi_ns_get_next_node + (ACPI_TYPE_ANY, child_node, NULL)) { + + /* There is at least one child of this node, visit it */ + + level++; + parent_node = child_node; + child_node = NULL; + } + } + } else { + /* + * No more children of this node (acpi_ns_get_next_node failed), go + * back upwards in the namespace tree to the node's parent. + */ + level--; + child_node = parent_node; + parent_node = acpi_ns_get_parent_node(parent_node); + } + } + + /* Complete walk, not terminated by user function */ + + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c new file mode 100644 index 000000000000..598393a04e5f --- /dev/null +++ b/drivers/acpi/acpica/nsxfeval.c @@ -0,0 +1,812 @@ +/******************************************************************************* + * + * Module Name: nsxfeval - Public interfaces to the ACPI subsystem + * ACPI Object evaluation interfaces + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsxfeval") + +/* Local prototypes */ +static void acpi_ns_resolve_references(struct acpi_evaluate_info *info); + +#ifdef ACPI_FUTURE_USAGE +/******************************************************************************* + * + * FUNCTION: acpi_evaluate_object_typed + * + * PARAMETERS: Handle - Object handle (optional) + * Pathname - Object pathname (optional) + * external_params - List of parameters to pass to method, + * terminated by NULL. May be NULL + * if no parameters are being passed. + * return_buffer - Where to put method's return value (if + * any). If NULL, no value is returned. + * return_type - Expected type of return object + * + * RETURN: Status + * + * DESCRIPTION: Find and evaluate the given object, passing the given + * parameters if necessary. One of "Handle" or "Pathname" must + * be valid (non-null) + * + ******************************************************************************/ + +acpi_status +acpi_evaluate_object_typed(acpi_handle handle, + acpi_string pathname, + struct acpi_object_list *external_params, + struct acpi_buffer *return_buffer, + acpi_object_type return_type) +{ + acpi_status status; + u8 must_free = FALSE; + + ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed); + + /* Return buffer must be valid */ + + if (!return_buffer) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { + must_free = TRUE; + } + + /* Evaluate the object */ + + status = + acpi_evaluate_object(handle, pathname, external_params, + return_buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Type ANY means "don't care" */ + + if (return_type == ACPI_TYPE_ANY) { + return_ACPI_STATUS(AE_OK); + } + + if (return_buffer->length == 0) { + + /* Error because caller specifically asked for a return value */ + + ACPI_ERROR((AE_INFO, "No return value")); + return_ACPI_STATUS(AE_NULL_OBJECT); + } + + /* Examine the object type returned from evaluate_object */ + + if (((union acpi_object *)return_buffer->pointer)->type == return_type) { + return_ACPI_STATUS(AE_OK); + } + + /* Return object type does not match requested type */ + + ACPI_ERROR((AE_INFO, + "Incorrect return type [%s] requested [%s]", + acpi_ut_get_type_name(((union acpi_object *)return_buffer-> + pointer)->type), + acpi_ut_get_type_name(return_type))); + + if (must_free) { + + /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ + + ACPI_FREE(return_buffer->pointer); + return_buffer->pointer = NULL; + } + + return_buffer->length = 0; + return_ACPI_STATUS(AE_TYPE); +} + +ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed) +#endif /* ACPI_FUTURE_USAGE */ +/******************************************************************************* + * + * FUNCTION: acpi_evaluate_object + * + * PARAMETERS: Handle - Object handle (optional) + * Pathname - Object pathname (optional) + * external_params - List of parameters to pass to method, + * terminated by NULL. May be NULL + * if no parameters are being passed. + * return_buffer - Where to put method's return value (if + * any). If NULL, no value is returned. + * + * RETURN: Status + * + * DESCRIPTION: Find and evaluate the given object, passing the given + * parameters if necessary. One of "Handle" or "Pathname" must + * be valid (non-null) + * + ******************************************************************************/ +acpi_status +acpi_evaluate_object(acpi_handle handle, + acpi_string pathname, + struct acpi_object_list *external_params, + struct acpi_buffer *return_buffer) +{ + acpi_status status; + struct acpi_evaluate_info *info; + acpi_size buffer_space_needed; + u32 i; + + ACPI_FUNCTION_TRACE(acpi_evaluate_object); + + /* Allocate and initialize the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->pathname = pathname; + + /* Convert and validate the device handle */ + + info->prefix_node = acpi_ns_map_handle_to_node(handle); + if (!info->prefix_node) { + status = AE_BAD_PARAMETER; + goto cleanup; + } + + /* + * If there are parameters to be passed to a control method, the external + * objects must all be converted to internal objects + */ + if (external_params && external_params->count) { + /* + * Allocate a new parameter block for the internal objects + * Add 1 to count to allow for null terminated internal list + */ + info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) + external_params-> + count + + 1) * sizeof(void *)); + if (!info->parameters) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Convert each external object in the list to an internal object */ + + for (i = 0; i < external_params->count; i++) { + status = + acpi_ut_copy_eobject_to_iobject(&external_params-> + pointer[i], + &info-> + parameters[i]); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + } + info->parameters[external_params->count] = NULL; + } + + /* + * Three major cases: + * 1) Fully qualified pathname + * 2) No handle, not fully qualified pathname (error) + * 3) Valid handle + */ + if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { + + /* The path is fully qualified, just evaluate by name */ + + info->prefix_node = NULL; + status = acpi_ns_evaluate(info); + } else if (!handle) { + /* + * A handle is optional iff a fully qualified pathname is specified. + * Since we've already handled fully qualified names above, this is + * an error + */ + if (!pathname) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Both Handle and Pathname are NULL")); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Null Handle with relative pathname [%s]", + pathname)); + } + + status = AE_BAD_PARAMETER; + } else { + /* We have a namespace a node and a possible relative path */ + + status = acpi_ns_evaluate(info); + } + + /* + * If we are expecting a return value, and all went well above, + * copy the return value to an external object. + */ + if (return_buffer) { + if (!info->return_object) { + return_buffer->length = 0; + } else { + if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) == + ACPI_DESC_TYPE_NAMED) { + /* + * If we received a NS Node as a return object, this means that + * the object we are evaluating has nothing interesting to + * return (such as a mutex, etc.) We return an error because + * these types are essentially unsupported by this interface. + * We don't check up front because this makes it easier to add + * support for various types at a later date if necessary. + */ + status = AE_TYPE; + info->return_object = NULL; /* No need to delete a NS Node */ + return_buffer->length = 0; + } + + if (ACPI_SUCCESS(status)) { + + /* Dereference Index and ref_of references */ + + acpi_ns_resolve_references(info); + + /* Get the size of the returned object */ + + status = + acpi_ut_get_object_size(info->return_object, + &buffer_space_needed); + if (ACPI_SUCCESS(status)) { + + /* Validate/Allocate/Clear caller buffer */ + + status = + acpi_ut_initialize_buffer + (return_buffer, + buffer_space_needed); + if (ACPI_FAILURE(status)) { + /* + * Caller's buffer is too small or a new one can't + * be allocated + */ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Needed buffer size %X, %s\n", + (u32) + buffer_space_needed, + acpi_format_exception + (status))); + } else { + /* We have enough space for the object, build it */ + + status = + acpi_ut_copy_iobject_to_eobject + (info->return_object, + return_buffer); + } + } + } + } + } + + if (info->return_object) { + /* + * Delete the internal return object. NOTE: Interpreter must be + * locked to avoid race condition. + */ + acpi_ex_enter_interpreter(); + + /* Remove one reference on the return object (should delete it) */ + + acpi_ut_remove_reference(info->return_object); + acpi_ex_exit_interpreter(); + } + + cleanup: + + /* Free the input parameter list (if we created one) */ + + if (info->parameters) { + + /* Free the allocated parameter block */ + + acpi_ut_delete_internal_object_list(info->parameters); + } + + ACPI_FREE(info); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_evaluate_object) + +/******************************************************************************* + * + * FUNCTION: acpi_ns_resolve_references + * + * PARAMETERS: Info - Evaluation info block + * + * RETURN: Info->return_object is replaced with the dereferenced object + * + * DESCRIPTION: Dereference certain reference objects. Called before an + * internal return object is converted to an external union acpi_object. + * + * Performs an automatic dereference of Index and ref_of reference objects. + * These reference objects are not supported by the union acpi_object, so this is a + * last resort effort to return something useful. Also, provides compatibility + * with other ACPI implementations. + * + * NOTE: does not handle references within returned package objects or nested + * references, but this support could be added later if found to be necessary. + * + ******************************************************************************/ +static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) +{ + union acpi_operand_object *obj_desc = NULL; + struct acpi_namespace_node *node; + + /* We are interested in reference objects only */ + + if (ACPI_GET_OBJECT_TYPE(info->return_object) != + ACPI_TYPE_LOCAL_REFERENCE) { + return; + } + + /* + * Two types of references are supported - those created by Index and + * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted + * to an union acpi_object, so it is not dereferenced here. A ddb_handle + * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to + * an union acpi_object. + */ + switch (info->return_object->reference.class) { + case ACPI_REFCLASS_INDEX: + + obj_desc = *(info->return_object->reference.where); + break; + + case ACPI_REFCLASS_REFOF: + + node = info->return_object->reference.object; + if (node) { + obj_desc = node->object; + } + break; + + default: + return; + } + + /* Replace the existing reference object */ + + if (obj_desc) { + acpi_ut_add_reference(obj_desc); + acpi_ut_remove_reference(info->return_object); + info->return_object = obj_desc; + } + + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_walk_namespace + * + * PARAMETERS: Type - acpi_object_type to search for + * start_object - Handle in namespace where search begins + * max_depth - Depth to which search is to reach + * user_function - Called when an object of "Type" is found + * Context - Passed to user function + * return_value - Location where return value of + * user_function is put if terminated early + * + * RETURNS Return value from the user_function if terminated early. + * Otherwise, returns NULL. + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the object specified by start_handle. + * The user_function is called whenever an object that matches + * the type parameter is found. If the user function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * The point of this procedure is to provide a generic namespace + * walk routine that can be called from multiple places to + * provide multiple services; the User Function can be tailored + * to each task, whether it is a print function, a compare + * function, etc. + * + ******************************************************************************/ + +acpi_status +acpi_walk_namespace(acpi_object_type type, + acpi_handle start_object, + u32 max_depth, + acpi_walk_callback user_function, + void *context, void **return_value) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_walk_namespace); + + /* Parameter validation */ + + if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Lock the namespace around the walk. + * The namespace will be unlocked/locked around each call + * to the user function - since this function + * must be allowed to make Acpi calls itself. + */ + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_ns_walk_namespace(type, start_object, max_depth, + ACPI_NS_WALK_UNLOCK, + user_function, context, return_value); + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_walk_namespace) + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_device_callback + * + * PARAMETERS: Callback from acpi_get_device + * + * RETURN: Status + * + * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non- + * present devices, or if they specified a HID, it filters based + * on that. + * + ******************************************************************************/ +static acpi_status +acpi_ns_get_device_callback(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value) +{ + struct acpi_get_devices_info *info = context; + acpi_status status; + struct acpi_namespace_node *node; + u32 flags; + struct acpica_device_id hid; + struct acpi_compatible_id_list *cid; + u32 i; + int found; + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + node = acpi_ns_map_handle_to_node(obj_handle); + status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + if (!node) { + return (AE_BAD_PARAMETER); + } + + /* Run _STA to determine if device is present */ + + status = acpi_ut_execute_STA(node, &flags); + if (ACPI_FAILURE(status)) { + return (AE_CTRL_DEPTH); + } + + if (!(flags & ACPI_STA_DEVICE_PRESENT) && + !(flags & ACPI_STA_DEVICE_FUNCTIONING)) { + /* + * Don't examine the children of the device only when the + * device is neither present nor functional. See ACPI spec, + * description of _STA for more information. + */ + return (AE_CTRL_DEPTH); + } + + /* Filter based on device HID & CID */ + + if (info->hid != NULL) { + status = acpi_ut_execute_HID(node, &hid); + if (status == AE_NOT_FOUND) { + return (AE_OK); + } else if (ACPI_FAILURE(status)) { + return (AE_CTRL_DEPTH); + } + + if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) { + + /* Get the list of Compatible IDs */ + + status = acpi_ut_execute_CID(node, &cid); + if (status == AE_NOT_FOUND) { + return (AE_OK); + } else if (ACPI_FAILURE(status)) { + return (AE_CTRL_DEPTH); + } + + /* Walk the CID list */ + + found = 0; + for (i = 0; i < cid->count; i++) { + if (ACPI_STRNCMP(cid->id[i].value, info->hid, + sizeof(struct + acpi_compatible_id)) == + 0) { + found = 1; + break; + } + } + ACPI_FREE(cid); + if (!found) + return (AE_OK); + } + } + + status = info->user_function(obj_handle, nesting_level, info->context, + return_value); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_get_devices + * + * PARAMETERS: HID - HID to search for. Can be NULL. + * user_function - Called when a matching object is found + * Context - Passed to user function + * return_value - Location where return value of + * user_function is put if terminated early + * + * RETURNS Return value from the user_function if terminated early. + * Otherwise, returns NULL. + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the object specified by start_handle. + * The user_function is called whenever an object of type + * Device is found. If the user function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * This is a wrapper for walk_namespace, but the callback performs + * additional filtering. Please see acpi_ns_get_device_callback. + * + ******************************************************************************/ + +acpi_status +acpi_get_devices(const char *HID, + acpi_walk_callback user_function, + void *context, void **return_value) +{ + acpi_status status; + struct acpi_get_devices_info info; + + ACPI_FUNCTION_TRACE(acpi_get_devices); + + /* Parameter validation */ + + if (!user_function) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * We're going to call their callback from OUR callback, so we need + * to know what it is, and their context parameter. + */ + info.hid = HID; + info.context = context; + info.user_function = user_function; + + /* + * Lock the namespace around the walk. + * The namespace will be unlocked/locked around each call + * to the user function - since this function + * must be allowed to make Acpi calls itself. + */ + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, + acpi_ns_get_device_callback, &info, + return_value); + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_devices) + +/******************************************************************************* + * + * FUNCTION: acpi_attach_data + * + * PARAMETERS: obj_handle - Namespace node + * Handler - Handler for this attachment + * Data - Pointer to data to be attached + * + * RETURN: Status + * + * DESCRIPTION: Attach arbitrary data and handler to a namespace node. + * + ******************************************************************************/ +acpi_status +acpi_attach_data(acpi_handle obj_handle, + acpi_object_handler handler, void *data) +{ + struct acpi_namespace_node *node; + acpi_status status; + + /* Parameter validation */ + + if (!obj_handle || !handler || !data) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Convert and validate the handle */ + + node = acpi_ns_map_handle_to_node(obj_handle); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + status = acpi_ns_attach_data(node, handler, data); + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_attach_data) + +/******************************************************************************* + * + * FUNCTION: acpi_detach_data + * + * PARAMETERS: obj_handle - Namespace node handle + * Handler - Handler used in call to acpi_attach_data + * + * RETURN: Status + * + * DESCRIPTION: Remove data that was previously attached to a node. + * + ******************************************************************************/ +acpi_status +acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) +{ + struct acpi_namespace_node *node; + acpi_status status; + + /* Parameter validation */ + + if (!obj_handle || !handler) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Convert and validate the handle */ + + node = acpi_ns_map_handle_to_node(obj_handle); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + status = acpi_ns_detach_data(node, handler); + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_detach_data) + +/******************************************************************************* + * + * FUNCTION: acpi_get_data + * + * PARAMETERS: obj_handle - Namespace node + * Handler - Handler used in call to attach_data + * Data - Where the data is returned + * + * RETURN: Status + * + * DESCRIPTION: Retrieve data that was previously attached to a namespace node. + * + ******************************************************************************/ +acpi_status +acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) +{ + struct acpi_namespace_node *node; + acpi_status status; + + /* Parameter validation */ + + if (!obj_handle || !handler || !data) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Convert and validate the handle */ + + node = acpi_ns_map_handle_to_node(obj_handle); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + status = acpi_ns_get_attached_data(node, handler, data); + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_data) diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c new file mode 100644 index 000000000000..7d5bfa9e9fe9 --- /dev/null +++ b/drivers/acpi/acpica/nsxfname.c @@ -0,0 +1,360 @@ +/****************************************************************************** + * + * Module Name: nsxfname - Public interfaces to the ACPI subsystem + * ACPI Namespace oriented interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsxfname") + +/****************************************************************************** + * + * FUNCTION: acpi_get_handle + * + * PARAMETERS: Parent - Object to search under (search scope). + * Pathname - Pointer to an asciiz string containing the + * name + * ret_handle - Where the return handle is returned + * + * RETURN: Status + * + * DESCRIPTION: This routine will search for a caller specified name in the + * name space. The caller can restrict the search region by + * specifying a non NULL parent. The parent value is itself a + * namespace handle. + * + ******************************************************************************/ +acpi_status +acpi_get_handle(acpi_handle parent, + acpi_string pathname, acpi_handle * ret_handle) +{ + acpi_status status; + struct acpi_namespace_node *node = NULL; + struct acpi_namespace_node *prefix_node = NULL; + + ACPI_FUNCTION_ENTRY(); + + /* Parameter Validation */ + + if (!ret_handle || !pathname) { + return (AE_BAD_PARAMETER); + } + + /* Convert a parent handle to a prefix node */ + + if (parent) { + prefix_node = acpi_ns_map_handle_to_node(parent); + if (!prefix_node) { + return (AE_BAD_PARAMETER); + } + } + + /* + * Valid cases are: + * 1) Fully qualified pathname + * 2) Parent + Relative pathname + * + * Error for + */ + if (acpi_ns_valid_root_prefix(pathname[0])) { + + /* Pathname is fully qualified (starts with '\') */ + + /* Special case for root-only, since we can't search for it */ + + if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) { + *ret_handle = + acpi_ns_convert_entry_to_handle(acpi_gbl_root_node); + return (AE_OK); + } + } else if (!prefix_node) { + + /* Relative path with null prefix is disallowed */ + + return (AE_BAD_PARAMETER); + } + + /* Find the Node and convert to a handle */ + + status = + acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node); + if (ACPI_SUCCESS(status)) { + *ret_handle = acpi_ns_convert_entry_to_handle(node); + } + + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_handle) + +/****************************************************************************** + * + * FUNCTION: acpi_get_name + * + * PARAMETERS: Handle - Handle to be converted to a pathname + * name_type - Full pathname or single segment + * Buffer - Buffer for returned path + * + * RETURN: Pointer to a string containing the fully qualified Name. + * + * DESCRIPTION: This routine returns the fully qualified name associated with + * the Handle parameter. This and the acpi_pathname_to_handle are + * complementary functions. + * + ******************************************************************************/ +acpi_status +acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) +{ + acpi_status status; + struct acpi_namespace_node *node; + + /* Parameter validation */ + + if (name_type > ACPI_NAME_TYPE_MAX) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_validate_buffer(buffer); + if (ACPI_FAILURE(status)) { + return (status); + } + + if (name_type == ACPI_FULL_PATHNAME) { + + /* Get the full pathname (From the namespace root) */ + + status = acpi_ns_handle_to_pathname(handle, buffer); + return (status); + } + + /* + * Wants the single segment ACPI name. + * Validate handle and convert to a namespace Node + */ + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + node = acpi_ns_map_handle_to_node(handle); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* Just copy the ACPI name from the Node and zero terminate it */ + + ACPI_STRNCPY(buffer->pointer, acpi_ut_get_node_name(node), + ACPI_NAME_SIZE); + ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0; + status = AE_OK; + + unlock_and_exit: + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_name) + +/****************************************************************************** + * + * FUNCTION: acpi_get_object_info + * + * PARAMETERS: Handle - Object Handle + * Buffer - Where the info is returned + * + * RETURN: Status + * + * DESCRIPTION: Returns information about an object as gleaned from the + * namespace node and possibly by running several standard + * control methods (Such as in the case of a device.) + * + ******************************************************************************/ +acpi_status +acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) +{ + acpi_status status; + struct acpi_namespace_node *node; + struct acpi_device_info *info; + struct acpi_device_info *return_info; + struct acpi_compatible_id_list *cid_list = NULL; + acpi_size size; + + /* Parameter validation */ + + if (!handle || !buffer) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_validate_buffer(buffer); + if (ACPI_FAILURE(status)) { + return (status); + } + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info)); + if (!info) { + return (AE_NO_MEMORY); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + node = acpi_ns_map_handle_to_node(handle); + if (!node) { + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + status = AE_BAD_PARAMETER; + goto cleanup; + } + + /* Init return structure */ + + size = sizeof(struct acpi_device_info); + + info->type = node->type; + info->name = node->name.integer; + info->valid = 0; + + if (node->type == ACPI_TYPE_METHOD) { + info->param_count = node->object->method.param_count; + } + + status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* If not a device, we are all done */ + + if (info->type == ACPI_TYPE_DEVICE) { + /* + * Get extra info for ACPI Devices objects only: + * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods. + * + * Note: none of these methods are required, so they may or may + * not be present for this device. The Info->Valid bitfield is used + * to indicate which methods were found and ran successfully. + */ + + /* Execute the Device._HID method */ + + status = acpi_ut_execute_HID(node, &info->hardware_id); + if (ACPI_SUCCESS(status)) { + info->valid |= ACPI_VALID_HID; + } + + /* Execute the Device._UID method */ + + status = acpi_ut_execute_UID(node, &info->unique_id); + if (ACPI_SUCCESS(status)) { + info->valid |= ACPI_VALID_UID; + } + + /* Execute the Device._CID method */ + + status = acpi_ut_execute_CID(node, &cid_list); + if (ACPI_SUCCESS(status)) { + size += cid_list->size; + info->valid |= ACPI_VALID_CID; + } + + /* Execute the Device._STA method */ + + status = acpi_ut_execute_STA(node, &info->current_status); + if (ACPI_SUCCESS(status)) { + info->valid |= ACPI_VALID_STA; + } + + /* Execute the Device._ADR method */ + + status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node, + &info->address); + if (ACPI_SUCCESS(status)) { + info->valid |= ACPI_VALID_ADR; + } + + /* Execute the Device._sx_d methods */ + + status = acpi_ut_execute_sxds(node, info->highest_dstates); + if (ACPI_SUCCESS(status)) { + info->valid |= ACPI_VALID_SXDS; + } + } + + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer(buffer, size); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Populate the return buffer */ + + return_info = buffer->pointer; + ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info)); + + if (cid_list) { + ACPI_MEMCPY(&return_info->compatibility_id, cid_list, + cid_list->size); + } + + cleanup: + ACPI_FREE(info); + if (cid_list) { + ACPI_FREE(cid_list); + } + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_object_info) diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c new file mode 100644 index 000000000000..80e6322d59c5 --- /dev/null +++ b/drivers/acpi/acpica/nsxfobj.c @@ -0,0 +1,287 @@ +/******************************************************************************* + * + * Module Name: nsxfobj - Public interfaces to the ACPI subsystem + * ACPI Object oriented interfaces + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsxfobj") + +/******************************************************************************* + * + * FUNCTION: acpi_get_id + * + * PARAMETERS: Handle - Handle of object whose id is desired + * ret_id - Where the id will be placed + * + * RETURN: Status + * + * DESCRIPTION: This routine returns the owner id associated with a handle + * + ******************************************************************************/ +acpi_status acpi_get_id(acpi_handle handle, acpi_owner_id * ret_id) +{ + struct acpi_namespace_node *node; + acpi_status status; + + /* Parameter Validation */ + + if (!ret_id) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Convert and validate the handle */ + + node = acpi_ns_map_handle_to_node(handle); + if (!node) { + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (AE_BAD_PARAMETER); + } + + *ret_id = node->owner_id; + + status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_id) + +/******************************************************************************* + * + * FUNCTION: acpi_get_type + * + * PARAMETERS: Handle - Handle of object whose type is desired + * ret_type - Where the type will be placed + * + * RETURN: Status + * + * DESCRIPTION: This routine returns the type associatd with a particular handle + * + ******************************************************************************/ +acpi_status acpi_get_type(acpi_handle handle, acpi_object_type * ret_type) +{ + struct acpi_namespace_node *node; + acpi_status status; + + /* Parameter Validation */ + + if (!ret_type) { + return (AE_BAD_PARAMETER); + } + + /* + * Special case for the predefined Root Node + * (return type ANY) + */ + if (handle == ACPI_ROOT_OBJECT) { + *ret_type = ACPI_TYPE_ANY; + return (AE_OK); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Convert and validate the handle */ + + node = acpi_ns_map_handle_to_node(handle); + if (!node) { + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (AE_BAD_PARAMETER); + } + + *ret_type = node->type; + + status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_type) + +/******************************************************************************* + * + * FUNCTION: acpi_get_parent + * + * PARAMETERS: Handle - Handle of object whose parent is desired + * ret_handle - Where the parent handle will be placed + * + * RETURN: Status + * + * DESCRIPTION: Returns a handle to the parent of the object represented by + * Handle. + * + ******************************************************************************/ +acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle) +{ + struct acpi_namespace_node *node; + acpi_status status; + + if (!ret_handle) { + return (AE_BAD_PARAMETER); + } + + /* Special case for the predefined Root Node (no parent) */ + + if (handle == ACPI_ROOT_OBJECT) { + return (AE_NULL_ENTRY); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Convert and validate the handle */ + + node = acpi_ns_map_handle_to_node(handle); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Get the parent entry */ + + *ret_handle = + acpi_ns_convert_entry_to_handle(acpi_ns_get_parent_node(node)); + + /* Return exception if parent is null */ + + if (!acpi_ns_get_parent_node(node)) { + status = AE_NULL_ENTRY; + } + + unlock_and_exit: + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_parent) + +/******************************************************************************* + * + * FUNCTION: acpi_get_next_object + * + * PARAMETERS: Type - Type of object to be searched for + * Parent - Parent object whose children we are getting + * last_child - Previous child that was found. + * The NEXT child will be returned + * ret_handle - Where handle to the next object is placed + * + * RETURN: Status + * + * DESCRIPTION: Return the next peer object within the namespace. If Handle is + * valid, Scope is ignored. Otherwise, the first object within + * Scope is returned. + * + ******************************************************************************/ +acpi_status +acpi_get_next_object(acpi_object_type type, + acpi_handle parent, + acpi_handle child, acpi_handle * ret_handle) +{ + acpi_status status; + struct acpi_namespace_node *node; + struct acpi_namespace_node *parent_node = NULL; + struct acpi_namespace_node *child_node = NULL; + + /* Parameter validation */ + + if (type > ACPI_TYPE_EXTERNAL_MAX) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* If null handle, use the parent */ + + if (!child) { + + /* Start search at the beginning of the specified scope */ + + parent_node = acpi_ns_map_handle_to_node(parent); + if (!parent_node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } else { + /* Non-null handle, ignore the parent */ + /* Convert and validate the handle */ + + child_node = acpi_ns_map_handle_to_node(child); + if (!child_node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } + + /* Internal function does the real work */ + + node = acpi_ns_get_next_node(type, parent_node, child_node); + if (!node) { + status = AE_NOT_FOUND; + goto unlock_and_exit; + } + + if (ret_handle) { + *ret_handle = acpi_ns_convert_entry_to_handle(node); + } + + unlock_and_exit: + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_next_object) diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c new file mode 100644 index 000000000000..852f3a83b2e6 --- /dev/null +++ b/drivers/acpi/acpica/psargs.c @@ -0,0 +1,752 @@ +/****************************************************************************** + * + * Module Name: psargs - Parse AML opcode arguments + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psargs") + +/* Local prototypes */ +static u32 +acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state); + +static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state + *parser_state); + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_next_package_length + * + * PARAMETERS: parser_state - Current parser state object + * + * RETURN: Decoded package length. On completion, the AML pointer points + * past the length byte or bytes. + * + * DESCRIPTION: Decode and return a package length field. + * Note: Largest package length is 28 bits, from ACPI specification + * + ******************************************************************************/ + +static u32 +acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) +{ + u8 *aml = parser_state->aml; + u32 package_length = 0; + u32 byte_count; + u8 byte_zero_mask = 0x3F; /* Default [0:5] */ + + ACPI_FUNCTION_TRACE(ps_get_next_package_length); + + /* + * Byte 0 bits [6:7] contain the number of additional bytes + * used to encode the package length, either 0,1,2, or 3 + */ + byte_count = (aml[0] >> 6); + parser_state->aml += ((acpi_size) byte_count + 1); + + /* Get bytes 3, 2, 1 as needed */ + + while (byte_count) { + /* + * Final bit positions for the package length bytes: + * Byte3->[20:27] + * Byte2->[12:19] + * Byte1->[04:11] + * Byte0->[00:03] + */ + package_length |= (aml[byte_count] << ((byte_count << 3) - 4)); + + byte_zero_mask = 0x0F; /* Use bits [0:3] of byte 0 */ + byte_count--; + } + + /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */ + + package_length |= (aml[0] & byte_zero_mask); + return_UINT32(package_length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_next_package_end + * + * PARAMETERS: parser_state - Current parser state object + * + * RETURN: Pointer to end-of-package +1 + * + * DESCRIPTION: Get next package length and return a pointer past the end of + * the package. Consumes the package length field + * + ******************************************************************************/ + +u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state) +{ + u8 *start = parser_state->aml; + u32 package_length; + + ACPI_FUNCTION_TRACE(ps_get_next_package_end); + + /* Function below updates parser_state->Aml */ + + package_length = acpi_ps_get_next_package_length(parser_state); + + return_PTR(start + package_length); /* end of package */ +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_next_namestring + * + * PARAMETERS: parser_state - Current parser state object + * + * RETURN: Pointer to the start of the name string (pointer points into + * the AML. + * + * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name + * prefix characters. Set parser state to point past the string. + * (Name is consumed from the AML.) + * + ******************************************************************************/ + +char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) +{ + u8 *start = parser_state->aml; + u8 *end = parser_state->aml; + + ACPI_FUNCTION_TRACE(ps_get_next_namestring); + + /* Point past any namestring prefix characters (backslash or carat) */ + + while (acpi_ps_is_prefix_char(*end)) { + end++; + } + + /* Decode the path prefix character */ + + switch (*end) { + case 0: + + /* null_name */ + + if (end == start) { + start = NULL; + } + end++; + break; + + case AML_DUAL_NAME_PREFIX: + + /* Two name segments */ + + end += 1 + (2 * ACPI_NAME_SIZE); + break; + + case AML_MULTI_NAME_PREFIX_OP: + + /* Multiple name segments, 4 chars each, count in next byte */ + + end += 2 + (*(end + 1) * ACPI_NAME_SIZE); + break; + + default: + + /* Single name segment */ + + end += ACPI_NAME_SIZE; + break; + } + + parser_state->aml = end; + return_PTR((char *)start); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_next_namepath + * + * PARAMETERS: parser_state - Current parser state object + * Arg - Where the namepath will be stored + * arg_count - If the namepath points to a control method + * the method's argument is returned here. + * possible_method_call - Whether the namepath can possibly be the + * start of a method call + * + * RETURN: Status + * + * DESCRIPTION: Get next name (if method call, return # of required args). + * Names are looked up in the internal namespace to determine + * if the name represents a control method. If a method + * is found, the number of arguments to the method is returned. + * This information is critical for parsing to continue correctly. + * + ******************************************************************************/ + +acpi_status +acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, + struct acpi_parse_state *parser_state, + union acpi_parse_object *arg, u8 possible_method_call) +{ + acpi_status status; + char *path; + union acpi_parse_object *name_op; + union acpi_operand_object *method_desc; + struct acpi_namespace_node *node; + u8 *start = parser_state->aml; + + ACPI_FUNCTION_TRACE(ps_get_next_namepath); + + path = acpi_ps_get_next_namestring(parser_state); + acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); + + /* Null path case is allowed, just exit */ + + if (!path) { + arg->common.value.name = path; + return_ACPI_STATUS(AE_OK); + } + + /* + * Lookup the name in the internal namespace, starting with the current + * scope. We don't want to add anything new to the namespace here, + * however, so we use MODE_EXECUTE. + * Allow searching of the parent tree, but don't open a new scope - + * we just want to lookup the object (must be mode EXECUTE to perform + * the upsearch) + */ + status = acpi_ns_lookup(walk_state->scope_info, path, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, + NULL, &node); + + /* + * If this name is a control method invocation, we must + * setup the method call + */ + if (ACPI_SUCCESS(status) && + possible_method_call && (node->type == ACPI_TYPE_METHOD)) { + if (walk_state->opcode == AML_UNLOAD_OP) { + /* + * acpi_ps_get_next_namestring has increased the AML pointer, + * so we need to restore the saved AML pointer for method call. + */ + walk_state->parser_state.aml = start; + walk_state->arg_count = 1; + acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); + return_ACPI_STATUS(AE_OK); + } + + /* This name is actually a control method invocation */ + + method_desc = acpi_ns_get_attached_object(node); + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Control Method - %p Desc %p Path=%p\n", node, + method_desc, path)); + + name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); + if (!name_op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Change Arg into a METHOD CALL and attach name to it */ + + acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); + name_op->common.value.name = path; + + /* Point METHODCALL/NAME to the METHOD Node */ + + name_op->common.node = node; + acpi_ps_append_arg(arg, name_op); + + if (!method_desc) { + ACPI_ERROR((AE_INFO, + "Control Method %p has no attached object", + node)); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Control Method - %p Args %X\n", + node, method_desc->method.param_count)); + + /* Get the number of arguments to expect */ + + walk_state->arg_count = method_desc->method.param_count; + return_ACPI_STATUS(AE_OK); + } + + /* + * Special handling if the name was not found during the lookup - + * some not_found cases are allowed + */ + if (status == AE_NOT_FOUND) { + + /* 1) not_found is ok during load pass 1/2 (allow forward references) */ + + if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) != + ACPI_PARSE_EXECUTE) { + status = AE_OK; + } + + /* 2) not_found during a cond_ref_of(x) is ok by definition */ + + else if (walk_state->op->common.aml_opcode == + AML_COND_REF_OF_OP) { + status = AE_OK; + } + + /* + * 3) not_found while building a Package is ok at this point, we + * may flag as an error later if slack mode is not enabled. + * (Some ASL code depends on allowing this behavior) + */ + else if ((arg->common.parent) && + ((arg->common.parent->common.aml_opcode == + AML_PACKAGE_OP) + || (arg->common.parent->common.aml_opcode == + AML_VAR_PACKAGE_OP))) { + status = AE_OK; + } + } + + /* Final exception check (may have been changed from code above) */ + + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(path, status); + + if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == + ACPI_PARSE_EXECUTE) { + + /* Report a control method execution error */ + + status = acpi_ds_method_error(status, walk_state); + } + } + + /* Save the namepath */ + + arg->common.value.name = path; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_next_simple_arg + * + * PARAMETERS: parser_state - Current parser state object + * arg_type - The argument type (AML_*_ARG) + * Arg - Where the argument is returned + * + * RETURN: None + * + * DESCRIPTION: Get the next simple argument (constant, string, or namestring) + * + ******************************************************************************/ + +void +acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, + u32 arg_type, union acpi_parse_object *arg) +{ + u32 length; + u16 opcode; + u8 *aml = parser_state->aml; + + ACPI_FUNCTION_TRACE_U32(ps_get_next_simple_arg, arg_type); + + switch (arg_type) { + case ARGP_BYTEDATA: + + /* Get 1 byte from the AML stream */ + + opcode = AML_BYTE_OP; + arg->common.value.integer = (acpi_integer) * aml; + length = 1; + break; + + case ARGP_WORDDATA: + + /* Get 2 bytes from the AML stream */ + + opcode = AML_WORD_OP; + ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml); + length = 2; + break; + + case ARGP_DWORDDATA: + + /* Get 4 bytes from the AML stream */ + + opcode = AML_DWORD_OP; + ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml); + length = 4; + break; + + case ARGP_QWORDDATA: + + /* Get 8 bytes from the AML stream */ + + opcode = AML_QWORD_OP; + ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml); + length = 8; + break; + + case ARGP_CHARLIST: + + /* Get a pointer to the string, point past the string */ + + opcode = AML_STRING_OP; + arg->common.value.string = ACPI_CAST_PTR(char, aml); + + /* Find the null terminator */ + + length = 0; + while (aml[length]) { + length++; + } + length++; + break; + + case ARGP_NAME: + case ARGP_NAMESTRING: + + acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); + arg->common.value.name = + acpi_ps_get_next_namestring(parser_state); + return_VOID; + + default: + + ACPI_ERROR((AE_INFO, "Invalid ArgType %X", arg_type)); + return_VOID; + } + + acpi_ps_init_op(arg, opcode); + parser_state->aml += length; + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_next_field + * + * PARAMETERS: parser_state - Current parser state object + * + * RETURN: A newly allocated FIELD op + * + * DESCRIPTION: Get next field (named_field, reserved_field, or access_field) + * + ******************************************************************************/ + +static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state + *parser_state) +{ + u32 aml_offset = (u32) + ACPI_PTR_DIFF(parser_state->aml, + parser_state->aml_start); + union acpi_parse_object *field; + u16 opcode; + u32 name; + + ACPI_FUNCTION_TRACE(ps_get_next_field); + + /* Determine field type */ + + switch (ACPI_GET8(parser_state->aml)) { + default: + + opcode = AML_INT_NAMEDFIELD_OP; + break; + + case 0x00: + + opcode = AML_INT_RESERVEDFIELD_OP; + parser_state->aml++; + break; + + case 0x01: + + opcode = AML_INT_ACCESSFIELD_OP; + parser_state->aml++; + break; + } + + /* Allocate a new field op */ + + field = acpi_ps_alloc_op(opcode); + if (!field) { + return_PTR(NULL); + } + + field->common.aml_offset = aml_offset; + + /* Decode the field type */ + + switch (opcode) { + case AML_INT_NAMEDFIELD_OP: + + /* Get the 4-character name */ + + ACPI_MOVE_32_TO_32(&name, parser_state->aml); + acpi_ps_set_name(field, name); + parser_state->aml += ACPI_NAME_SIZE; + + /* Get the length which is encoded as a package length */ + + field->common.value.size = + acpi_ps_get_next_package_length(parser_state); + break; + + case AML_INT_RESERVEDFIELD_OP: + + /* Get the length which is encoded as a package length */ + + field->common.value.size = + acpi_ps_get_next_package_length(parser_state); + break; + + case AML_INT_ACCESSFIELD_OP: + + /* + * Get access_type and access_attrib and merge into the field Op + * access_type is first operand, access_attribute is second + */ + field->common.value.integer = + (((u32) ACPI_GET8(parser_state->aml) << 8)); + parser_state->aml++; + field->common.value.integer |= ACPI_GET8(parser_state->aml); + parser_state->aml++; + break; + + default: + + /* Opcode was set in previous switch */ + break; + } + + return_PTR(field); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_next_arg + * + * PARAMETERS: walk_state - Current state + * parser_state - Current parser state object + * arg_type - The argument type (AML_*_ARG) + * return_arg - Where the next arg is returned + * + * RETURN: Status, and an op object containing the next argument. + * + * DESCRIPTION: Get next argument (including complex list arguments that require + * pushing the parser stack) + * + ******************************************************************************/ + +acpi_status +acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, + struct acpi_parse_state *parser_state, + u32 arg_type, union acpi_parse_object **return_arg) +{ + union acpi_parse_object *arg = NULL; + union acpi_parse_object *prev = NULL; + union acpi_parse_object *field; + u32 subop; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_PTR(ps_get_next_arg, parser_state); + + switch (arg_type) { + case ARGP_BYTEDATA: + case ARGP_WORDDATA: + case ARGP_DWORDDATA: + case ARGP_CHARLIST: + case ARGP_NAME: + case ARGP_NAMESTRING: + + /* Constants, strings, and namestrings are all the same size */ + + arg = acpi_ps_alloc_op(AML_BYTE_OP); + if (!arg) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + acpi_ps_get_next_simple_arg(parser_state, arg_type, arg); + break; + + case ARGP_PKGLENGTH: + + /* Package length, nothing returned */ + + parser_state->pkg_end = + acpi_ps_get_next_package_end(parser_state); + break; + + case ARGP_FIELDLIST: + + if (parser_state->aml < parser_state->pkg_end) { + + /* Non-empty list */ + + while (parser_state->aml < parser_state->pkg_end) { + field = acpi_ps_get_next_field(parser_state); + if (!field) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + if (prev) { + prev->common.next = field; + } else { + arg = field; + } + prev = field; + } + + /* Skip to End of byte data */ + + parser_state->aml = parser_state->pkg_end; + } + break; + + case ARGP_BYTELIST: + + if (parser_state->aml < parser_state->pkg_end) { + + /* Non-empty list */ + + arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP); + if (!arg) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Fill in bytelist data */ + + arg->common.value.size = (u32) + ACPI_PTR_DIFF(parser_state->pkg_end, + parser_state->aml); + arg->named.data = parser_state->aml; + + /* Skip to End of byte data */ + + parser_state->aml = parser_state->pkg_end; + } + break; + + case ARGP_TARGET: + case ARGP_SUPERNAME: + case ARGP_SIMPLENAME: + + subop = acpi_ps_peek_opcode(parser_state); + if (subop == 0 || + acpi_ps_is_leading_char(subop) || + acpi_ps_is_prefix_char(subop)) { + + /* null_name or name_string */ + + arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); + if (!arg) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* To support super_name arg of Unload */ + + if (walk_state->opcode == AML_UNLOAD_OP) { + status = + acpi_ps_get_next_namepath(walk_state, + parser_state, arg, + 1); + + /* + * If the super_name arg of Unload is a method call, + * we have restored the AML pointer, just free this Arg + */ + if (arg->common.aml_opcode == + AML_INT_METHODCALL_OP) { + acpi_ps_free_op(arg); + arg = NULL; + } + } else { + status = + acpi_ps_get_next_namepath(walk_state, + parser_state, arg, + 0); + } + } else { + /* Single complex argument, nothing returned */ + + walk_state->arg_count = 1; + } + break; + + case ARGP_DATAOBJ: + case ARGP_TERMARG: + + /* Single complex argument, nothing returned */ + + walk_state->arg_count = 1; + break; + + case ARGP_DATAOBJLIST: + case ARGP_TERMLIST: + case ARGP_OBJLIST: + + if (parser_state->aml < parser_state->pkg_end) { + + /* Non-empty list of variable arguments, nothing returned */ + + walk_state->arg_count = ACPI_VAR_ARGS; + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Invalid ArgType: %X", arg_type)); + status = AE_AML_OPERAND_TYPE; + break; + } + + *return_arg = arg; + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c new file mode 100644 index 000000000000..fd6648f0d65f --- /dev/null +++ b/drivers/acpi/acpica/psloop.c @@ -0,0 +1,1088 @@ +/****************************************************************************** + * + * Module Name: psloop - Main AML parse loop + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * Parse the AML and build an operation tree as most interpreters, (such as + * Perl) do. Parsing is done by hand rather than with a YACC generated parser + * to tightly constrain stack and dynamic memory usage. Parsing is kept + * flexible and the code fairly compact by parsing based on a list of AML + * opcode templates in aml_op_info[]. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psloop") + +static u32 acpi_gbl_depth = 0; + +/* Local prototypes */ + +static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state); + +static acpi_status +acpi_ps_build_named_op(struct acpi_walk_state *walk_state, + u8 * aml_op_start, + union acpi_parse_object *unnamed_op, + union acpi_parse_object **op); + +static acpi_status +acpi_ps_create_op(struct acpi_walk_state *walk_state, + u8 * aml_op_start, union acpi_parse_object **new_op); + +static acpi_status +acpi_ps_get_arguments(struct acpi_walk_state *walk_state, + u8 * aml_op_start, union acpi_parse_object *op); + +static acpi_status +acpi_ps_complete_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **op, acpi_status status); + +static acpi_status +acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, acpi_status status); + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_aml_opcode + * + * PARAMETERS: walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Extract the next AML opcode from the input stream. + * + ******************************************************************************/ + +static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) +{ + + ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); + + walk_state->aml_offset = + (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, + walk_state->parser_state.aml_start); + walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); + + /* + * First cut to determine what we have found: + * 1) A valid AML opcode + * 2) A name string + * 3) An unknown/invalid opcode + */ + walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); + + switch (walk_state->op_info->class) { + case AML_CLASS_ASCII: + case AML_CLASS_PREFIX: + /* + * Starts with a valid prefix or ASCII char, this is a name + * string. Convert the bare name string to a namepath. + */ + walk_state->opcode = AML_INT_NAMEPATH_OP; + walk_state->arg_types = ARGP_NAMESTRING; + break; + + case AML_CLASS_UNKNOWN: + + /* The opcode is unrecognized. Just skip unknown opcodes */ + + ACPI_ERROR((AE_INFO, + "Found unknown opcode %X at AML address %p offset %X, ignoring", + walk_state->opcode, walk_state->parser_state.aml, + walk_state->aml_offset)); + + ACPI_DUMP_BUFFER(walk_state->parser_state.aml, 128); + + /* Assume one-byte bad opcode */ + + walk_state->parser_state.aml++; + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + + default: + + /* Found opcode info, this is a normal opcode */ + + walk_state->parser_state.aml += + acpi_ps_get_opcode_size(walk_state->opcode); + walk_state->arg_types = walk_state->op_info->parse_args; + break; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_build_named_op + * + * PARAMETERS: walk_state - Current state + * aml_op_start - Begin of named Op in AML + * unnamed_op - Early Op (not a named Op) + * Op - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Parse a named Op + * + ******************************************************************************/ + +static acpi_status +acpi_ps_build_named_op(struct acpi_walk_state *walk_state, + u8 * aml_op_start, + union acpi_parse_object *unnamed_op, + union acpi_parse_object **op) +{ + acpi_status status = AE_OK; + union acpi_parse_object *arg = NULL; + + ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); + + unnamed_op->common.value.arg = NULL; + unnamed_op->common.arg_list_length = 0; + unnamed_op->common.aml_opcode = walk_state->opcode; + + /* + * Get and append arguments until we find the node that contains + * the name (the type ARGP_NAME). + */ + while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && + (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) { + status = + acpi_ps_get_next_arg(walk_state, + &(walk_state->parser_state), + GET_CURRENT_ARG_TYPE(walk_state-> + arg_types), &arg); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ps_append_arg(unnamed_op, arg); + INCREMENT_ARG_LIST(walk_state->arg_types); + } + + /* + * Make sure that we found a NAME and didn't run out of arguments + */ + if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) { + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + /* We know that this arg is a name, move to next arg */ + + INCREMENT_ARG_LIST(walk_state->arg_types); + + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = NULL; + + status = walk_state->descending_callback(walk_state, op); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); + return_ACPI_STATUS(status); + } + + if (!*op) { + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + } + + status = acpi_ps_next_parse_state(walk_state, *op, status); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_PENDING) { + return_ACPI_STATUS(AE_CTRL_PARSE_PENDING); + } + return_ACPI_STATUS(status); + } + + acpi_ps_append_arg(*op, unnamed_op->common.value.arg); + acpi_gbl_depth++; + + if ((*op)->common.aml_opcode == AML_REGION_OP || + (*op)->common.aml_opcode == AML_DATA_REGION_OP) { + /* + * Defer final parsing of an operation_region body, because we don't + * have enough info in the first pass to parse it correctly (i.e., + * there may be method calls within the term_arg elements of the body.) + * + * However, we must continue parsing because the opregion is not a + * standalone package -- we don't know where the end is at this point. + * + * (Length is unknown until parse of the body complete) + */ + (*op)->named.data = aml_op_start; + (*op)->named.length = 0; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_create_op + * + * PARAMETERS: walk_state - Current state + * aml_op_start - Op start in AML + * new_op - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Get Op from AML + * + ******************************************************************************/ + +static acpi_status +acpi_ps_create_op(struct acpi_walk_state *walk_state, + u8 * aml_op_start, union acpi_parse_object **new_op) +{ + acpi_status status = AE_OK; + union acpi_parse_object *op; + union acpi_parse_object *named_op = NULL; + union acpi_parse_object *parent_scope; + u8 argument_count; + const struct acpi_opcode_info *op_info; + + ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); + + status = acpi_ps_get_aml_opcode(walk_state); + if (status == AE_CTRL_PARSE_CONTINUE) { + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + } + + /* Create Op structure and append to parent's argument list */ + + walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); + op = acpi_ps_alloc_op(walk_state->opcode); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + if (walk_state->op_info->flags & AML_NAMED) { + status = + acpi_ps_build_named_op(walk_state, aml_op_start, op, + &named_op); + acpi_ps_free_op(op); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + *new_op = named_op; + return_ACPI_STATUS(AE_OK); + } + + /* Not a named opcode, just allocate Op and append to parent */ + + if (walk_state->op_info->flags & AML_CREATE) { + /* + * Backup to beginning of create_xXXfield declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + + if (walk_state->opcode == AML_BANK_FIELD_OP) { + /* + * Backup to beginning of bank_field declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + + parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); + acpi_ps_append_arg(parent_scope, op); + + if (parent_scope) { + op_info = + acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); + if (op_info->flags & AML_HAS_TARGET) { + argument_count = + acpi_ps_get_argument_count(op_info->type); + if (parent_scope->common.arg_list_length > + argument_count) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } + + if (walk_state->descending_callback != NULL) { + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = *new_op = op; + + status = walk_state->descending_callback(walk_state, &op); + status = acpi_ps_next_parse_state(walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_CTRL_PARSE_PENDING; + } + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_arguments + * + * PARAMETERS: walk_state - Current state + * aml_op_start - Op start in AML + * Op - Current Op + * + * RETURN: Status + * + * DESCRIPTION: Get arguments for passed Op. + * + ******************************************************************************/ + +static acpi_status +acpi_ps_get_arguments(struct acpi_walk_state *walk_state, + u8 * aml_op_start, union acpi_parse_object *op) +{ + acpi_status status = AE_OK; + union acpi_parse_object *arg = NULL; + + ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state); + + switch (op->common.aml_opcode) { + case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ + case AML_WORD_OP: /* AML_WORDDATA_ARG */ + case AML_DWORD_OP: /* AML_DWORDATA_ARG */ + case AML_QWORD_OP: /* AML_QWORDATA_ARG */ + case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ + + /* Fill in constant or string argument directly */ + + acpi_ps_get_next_simple_arg(&(walk_state->parser_state), + GET_CURRENT_ARG_TYPE(walk_state-> + arg_types), + op); + break; + + case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ + + status = + acpi_ps_get_next_namepath(walk_state, + &(walk_state->parser_state), op, + 1); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + walk_state->arg_types = 0; + break; + + default: + /* + * Op is not a constant or string, append each argument to the Op + */ + while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) + && !walk_state->arg_count) { + walk_state->aml_offset = + (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, + walk_state->parser_state. + aml_start); + + status = + acpi_ps_get_next_arg(walk_state, + &(walk_state->parser_state), + GET_CURRENT_ARG_TYPE + (walk_state->arg_types), &arg); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (arg) { + arg->common.aml_offset = walk_state->aml_offset; + acpi_ps_append_arg(op, arg); + } + + INCREMENT_ARG_LIST(walk_state->arg_types); + } + + /* Special processing for certain opcodes */ + + /* TBD (remove): Temporary mechanism to disable this code if needed */ + +#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE + + if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) && + ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { + /* + * We want to skip If/Else/While constructs during Pass1 because we + * want to actually conditionally execute the code during Pass2. + * + * Except for disassembly, where we always want to walk the + * If/Else/While packages + */ + switch (op->common.aml_opcode) { + case AML_IF_OP: + case AML_ELSE_OP: + case AML_WHILE_OP: + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Pass1: Skipping an If/Else/While body\n")); + + /* Skip body of if/else/while in pass 1 */ + + walk_state->parser_state.aml = + walk_state->parser_state.pkg_end; + walk_state->arg_count = 0; + break; + + default: + break; + } + } +#endif + + switch (op->common.aml_opcode) { + case AML_METHOD_OP: + /* + * Skip parsing of control method because we don't have enough + * info in the first pass to parse it correctly. + * + * Save the length and address of the body + */ + op->named.data = walk_state->parser_state.aml; + op->named.length = (u32) + (walk_state->parser_state.pkg_end - + walk_state->parser_state.aml); + + /* Skip body of method */ + + walk_state->parser_state.aml = + walk_state->parser_state.pkg_end; + walk_state->arg_count = 0; + break; + + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + if ((op->common.parent) && + (op->common.parent->common.aml_opcode == + AML_NAME_OP) + && (walk_state->pass_number <= + ACPI_IMODE_LOAD_PASS2)) { + /* + * Skip parsing of Buffers and Packages because we don't have + * enough info in the first pass to parse them correctly. + */ + op->named.data = aml_op_start; + op->named.length = (u32) + (walk_state->parser_state.pkg_end - + aml_op_start); + + /* Skip body */ + + walk_state->parser_state.aml = + walk_state->parser_state.pkg_end; + walk_state->arg_count = 0; + } + break; + + case AML_WHILE_OP: + + if (walk_state->control_state) { + walk_state->control_state->control.package_end = + walk_state->parser_state.pkg_end; + } + break; + + default: + + /* No action for all other opcodes */ + break; + } + + break; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_complete_op + * + * PARAMETERS: walk_state - Current state + * Op - Returned Op + * Status - Parse status before complete Op + * + * RETURN: Status + * + * DESCRIPTION: Complete Op + * + ******************************************************************************/ + +static acpi_status +acpi_ps_complete_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **op, acpi_status status) +{ + acpi_status status2; + + ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); + + /* + * Finished one argument of the containing scope + */ + walk_state->parser_state.scope->parse_scope.arg_count--; + + /* Close this Op (will result in parse subtree deletion) */ + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + *op = NULL; + + switch (status) { + case AE_OK: + break; + + case AE_CTRL_TRANSFER: + + /* We are about to transfer to a called method */ + + walk_state->prev_op = NULL; + walk_state->prev_arg_types = walk_state->arg_types; + return_ACPI_STATUS(status); + + case AE_CTRL_END: + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + if (*op) { + walk_state->op = *op; + walk_state->op_info = + acpi_ps_get_opcode_info((*op)->common.aml_opcode); + walk_state->opcode = (*op)->common.aml_opcode; + + status = walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, *op, status); + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + status = AE_OK; + break; + + case AE_CTRL_BREAK: + case AE_CTRL_CONTINUE: + + /* Pop off scopes until we find the While */ + + while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + } + + /* Close this iteration of the While loop */ + + walk_state->op = *op; + walk_state->op_info = + acpi_ps_get_opcode_info((*op)->common.aml_opcode); + walk_state->opcode = (*op)->common.aml_opcode; + + status = walk_state->ascending_callback(walk_state); + status = acpi_ps_next_parse_state(walk_state, *op, status); + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + status = AE_OK; + break; + + case AE_CTRL_TERMINATE: + + /* Clean up */ + do { + if (*op) { + status2 = + acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + acpi_ut_delete_generic_state + (acpi_ut_pop_generic_state + (&walk_state->control_state)); + } + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (*op); + + return_ACPI_STATUS(AE_OK); + + default: /* All other non-AE_OK status */ + + do { + if (*op) { + status2 = + acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (*op); + +#if 0 + /* + * TBD: Cleanup parse ops on error + */ + if (*op == NULL) { + acpi_ps_pop_scope(parser_state, op, + &walk_state->arg_types, + &walk_state->arg_count); + } +#endif + walk_state->prev_op = NULL; + walk_state->prev_arg_types = walk_state->arg_types; + return_ACPI_STATUS(status); + } + + /* This scope complete? */ + + if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); + } else { + *op = NULL; + } + + ACPI_PREEMPTION_POINT(); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_complete_final_op + * + * PARAMETERS: walk_state - Current state + * Op - Current Op + * Status - Current parse status before complete last + * Op + * + * RETURN: Status + * + * DESCRIPTION: Complete last Op. + * + ******************************************************************************/ + +static acpi_status +acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, acpi_status status) +{ + acpi_status status2; + + ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); + + /* + * Complete the last Op (if not completed), and clear the scope stack. + * It is easily possible to end an AML "package" with an unbounded number + * of open scopes (such as when several ASL blocks are closed with + * sequential closing braces). We want to terminate each one cleanly. + */ + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", + op)); + do { + if (op) { + if (walk_state->ascending_callback != NULL) { + walk_state->op = op; + walk_state->op_info = + acpi_ps_get_opcode_info(op->common. + aml_opcode); + walk_state->opcode = op->common.aml_opcode; + + status = + walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, op, + status); + if (status == AE_CTRL_PENDING) { + status = + acpi_ps_complete_op(walk_state, &op, + AE_OK); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + if (status == AE_CTRL_TERMINATE) { + status = AE_OK; + + /* Clean up */ + do { + if (op) { + status2 = + acpi_ps_complete_this_op + (walk_state, op); + if (ACPI_FAILURE + (status2)) { + return_ACPI_STATUS + (status2); + } + } + + acpi_ps_pop_scope(& + (walk_state-> + parser_state), + &op, + &walk_state-> + arg_types, + &walk_state-> + arg_count); + + } while (op); + + return_ACPI_STATUS(status); + } + + else if (ACPI_FAILURE(status)) { + + /* First error is most important */ + + (void) + acpi_ps_complete_this_op(walk_state, + op); + return_ACPI_STATUS(status); + } + } + + status2 = acpi_ps_complete_this_op(walk_state, op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + acpi_ps_pop_scope(&(walk_state->parser_state), &op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (op); + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_parse_loop + * + * PARAMETERS: walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Parse AML (pointed to by the current parser state) and return + * a tree of ops. + * + ******************************************************************************/ + +acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_parse_object *op = NULL; /* current op */ + struct acpi_parse_state *parser_state; + u8 *aml_op_start = NULL; + + ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state); + + if (walk_state->descending_callback == NULL) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + parser_state = &walk_state->parser_state; + walk_state->arg_types = 0; + +#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) + + if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { + + /* We are restarting a preempted control method */ + + if (acpi_ps_has_completed_scope(parser_state)) { + /* + * We must check if a predicate to an IF or WHILE statement + * was just completed + */ + if ((parser_state->scope->parse_scope.op) && + ((parser_state->scope->parse_scope.op->common. + aml_opcode == AML_IF_OP) + || (parser_state->scope->parse_scope.op->common. + aml_opcode == AML_WHILE_OP)) + && (walk_state->control_state) + && (walk_state->control_state->common.state == + ACPI_CONTROL_PREDICATE_EXECUTING)) { + /* + * A predicate was just completed, get the value of the + * predicate and branch based on that value + */ + walk_state->op = NULL; + status = + acpi_ds_get_predicate_value(walk_state, + ACPI_TO_POINTER + (TRUE)); + if (ACPI_FAILURE(status) + && ((status & AE_CODE_MASK) != + AE_CODE_CONTROL)) { + if (status == AE_AML_NO_RETURN_VALUE) { + ACPI_EXCEPTION((AE_INFO, status, + "Invoked method did not return a value")); + + } + + ACPI_EXCEPTION((AE_INFO, status, + "GetPredicate Failed")); + return_ACPI_STATUS(status); + } + + status = + acpi_ps_next_parse_state(walk_state, op, + status); + } + + acpi_ps_pop_scope(parser_state, &op, + &walk_state->arg_types, + &walk_state->arg_count); + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Popped scope, Op=%p\n", op)); + } else if (walk_state->prev_op) { + + /* We were in the middle of an op */ + + op = walk_state->prev_op; + walk_state->arg_types = walk_state->prev_arg_types; + } + } +#endif + + /* Iterative parsing loop, while there is more AML to process: */ + + while ((parser_state->aml < parser_state->aml_end) || (op)) { + aml_op_start = parser_state->aml; + if (!op) { + status = + acpi_ps_create_op(walk_state, aml_op_start, &op); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_PARSE_CONTINUE) { + continue; + } + + if (status == AE_CTRL_PARSE_PENDING) { + status = AE_OK; + } + + status = + acpi_ps_complete_op(walk_state, &op, + status); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + continue; + } + + op->common.aml_offset = walk_state->aml_offset; + + if (walk_state->op_info) { + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", + (u32) op->common.aml_opcode, + walk_state->op_info->name, op, + parser_state->aml, + op->common.aml_offset)); + } + } + + /* + * Start arg_count at zero because we don't know if there are + * any args yet + */ + walk_state->arg_count = 0; + + /* Are there any arguments that must be processed? */ + + if (walk_state->arg_types) { + + /* Get arguments */ + + status = + acpi_ps_get_arguments(walk_state, aml_op_start, op); + if (ACPI_FAILURE(status)) { + status = + acpi_ps_complete_op(walk_state, &op, + status); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + continue; + } + } + + /* Check for arguments that need to be processed */ + + if (walk_state->arg_count) { + /* + * There are arguments (complex ones), push Op and + * prepare for argument + */ + status = acpi_ps_push_scope(parser_state, op, + walk_state->arg_types, + walk_state->arg_count); + if (ACPI_FAILURE(status)) { + status = + acpi_ps_complete_op(walk_state, &op, + status); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + continue; + } + + op = NULL; + continue; + } + + /* + * All arguments have been processed -- Op is complete, + * prepare for next + */ + walk_state->op_info = + acpi_ps_get_opcode_info(op->common.aml_opcode); + if (walk_state->op_info->flags & AML_NAMED) { + if (acpi_gbl_depth) { + acpi_gbl_depth--; + } + + if (op->common.aml_opcode == AML_REGION_OP || + op->common.aml_opcode == AML_DATA_REGION_OP) { + /* + * Skip parsing of control method or opregion body, + * because we don't have enough info in the first pass + * to parse them correctly. + * + * Completed parsing an op_region declaration, we now + * know the length. + */ + op->named.length = + (u32) (parser_state->aml - op->named.data); + } + } + + if (walk_state->op_info->flags & AML_CREATE) { + /* + * Backup to beginning of create_xXXfield declaration (1 for + * Opcode) + * + * body_length is unknown until we parse the body + */ + op->named.length = + (u32) (parser_state->aml - op->named.data); + } + + if (op->common.aml_opcode == AML_BANK_FIELD_OP) { + /* + * Backup to beginning of bank_field declaration + * + * body_length is unknown until we parse the body + */ + op->named.length = + (u32) (parser_state->aml - op->named.data); + } + + /* This op complete, notify the dispatcher */ + + if (walk_state->ascending_callback != NULL) { + walk_state->op = op; + walk_state->opcode = op->common.aml_opcode; + + status = walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + } + } + + status = acpi_ps_complete_op(walk_state, &op, status); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + } /* while parser_state->Aml */ + + status = acpi_ps_complete_final_op(walk_state, op, status); + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c new file mode 100644 index 000000000000..3693a121b347 --- /dev/null +++ b/drivers/acpi/acpica/psopcode.c @@ -0,0 +1,810 @@ +/****************************************************************************** + * + * Module Name: psopcode - Parser/Interpreter opcode information table + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psopcode") + +static const u8 acpi_gbl_argument_count[] = + { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; + +/******************************************************************************* + * + * NAME: acpi_gbl_aml_op_info + * + * DESCRIPTION: Opcode table. Each entry contains + * The name is a simple ascii string, the operand specifier is an + * ascii string with one letter per operand. The letter specifies + * the operand type. + * + ******************************************************************************/ + +/* + * Summary of opcode types/flags + * + + Opcodes that have associated namespace objects (AML_NSOBJECT flag) + + AML_SCOPE_OP + AML_DEVICE_OP + AML_THERMAL_ZONE_OP + AML_METHOD_OP + AML_POWER_RES_OP + AML_PROCESSOR_OP + AML_FIELD_OP + AML_INDEX_FIELD_OP + AML_BANK_FIELD_OP + AML_NAME_OP + AML_ALIAS_OP + AML_MUTEX_OP + AML_EVENT_OP + AML_REGION_OP + AML_CREATE_FIELD_OP + AML_CREATE_BIT_FIELD_OP + AML_CREATE_BYTE_FIELD_OP + AML_CREATE_WORD_FIELD_OP + AML_CREATE_DWORD_FIELD_OP + AML_CREATE_QWORD_FIELD_OP + AML_INT_NAMEDFIELD_OP + AML_INT_METHODCALL_OP + AML_INT_NAMEPATH_OP + + Opcodes that are "namespace" opcodes (AML_NSOPCODE flag) + + AML_SCOPE_OP + AML_DEVICE_OP + AML_THERMAL_ZONE_OP + AML_METHOD_OP + AML_POWER_RES_OP + AML_PROCESSOR_OP + AML_FIELD_OP + AML_INDEX_FIELD_OP + AML_BANK_FIELD_OP + AML_NAME_OP + AML_ALIAS_OP + AML_MUTEX_OP + AML_EVENT_OP + AML_REGION_OP + AML_INT_NAMEDFIELD_OP + + Opcodes that have an associated namespace node (AML_NSNODE flag) + + AML_SCOPE_OP + AML_DEVICE_OP + AML_THERMAL_ZONE_OP + AML_METHOD_OP + AML_POWER_RES_OP + AML_PROCESSOR_OP + AML_NAME_OP + AML_ALIAS_OP + AML_MUTEX_OP + AML_EVENT_OP + AML_REGION_OP + AML_CREATE_FIELD_OP + AML_CREATE_BIT_FIELD_OP + AML_CREATE_BYTE_FIELD_OP + AML_CREATE_WORD_FIELD_OP + AML_CREATE_DWORD_FIELD_OP + AML_CREATE_QWORD_FIELD_OP + AML_INT_NAMEDFIELD_OP + AML_INT_METHODCALL_OP + AML_INT_NAMEPATH_OP + + Opcodes that define named ACPI objects (AML_NAMED flag) + + AML_SCOPE_OP + AML_DEVICE_OP + AML_THERMAL_ZONE_OP + AML_METHOD_OP + AML_POWER_RES_OP + AML_PROCESSOR_OP + AML_NAME_OP + AML_ALIAS_OP + AML_MUTEX_OP + AML_EVENT_OP + AML_REGION_OP + AML_INT_NAMEDFIELD_OP + + Opcodes that contain executable AML as part of the definition that + must be deferred until needed + + AML_METHOD_OP + AML_VAR_PACKAGE_OP + AML_CREATE_FIELD_OP + AML_CREATE_BIT_FIELD_OP + AML_CREATE_BYTE_FIELD_OP + AML_CREATE_WORD_FIELD_OP + AML_CREATE_DWORD_FIELD_OP + AML_CREATE_QWORD_FIELD_OP + AML_REGION_OP + AML_BUFFER_OP + + Field opcodes + + AML_CREATE_FIELD_OP + AML_FIELD_OP + AML_INDEX_FIELD_OP + AML_BANK_FIELD_OP + + Field "Create" opcodes + + AML_CREATE_FIELD_OP + AML_CREATE_BIT_FIELD_OP + AML_CREATE_BYTE_FIELD_OP + AML_CREATE_WORD_FIELD_OP + AML_CREATE_DWORD_FIELD_OP + AML_CREATE_QWORD_FIELD_OP + + ******************************************************************************/ + +/* + * Master Opcode information table. A summary of everything we know about each + * opcode, all in one place. + */ +const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { +/*! [Begin] no source code translation */ +/* Index Name Parser Args Interpreter Args ObjectType Class Type Flags */ + +/* 00 */ ACPI_OP("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER, + AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), +/* 01 */ ACPI_OP("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER, + AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), +/* 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), +/* 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), +/* 04 */ ACPI_OP("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP, + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), +/* 05 */ ACPI_OP("WordConst", ARGP_WORD_OP, ARGI_WORD_OP, + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), +/* 06 */ ACPI_OP("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP, + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), +/* 07 */ ACPI_OP("String", ARGP_STRING_OP, ARGI_STRING_OP, + ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), +/* 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), +/* 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), +/* 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), +/* 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), +/* 0C */ ACPI_OP("Local0", ARGP_LOCAL0, ARGI_LOCAL0, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), +/* 0D */ ACPI_OP("Local1", ARGP_LOCAL1, ARGI_LOCAL1, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), +/* 0E */ ACPI_OP("Local2", ARGP_LOCAL2, ARGI_LOCAL2, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), +/* 0F */ ACPI_OP("Local3", ARGP_LOCAL3, ARGI_LOCAL3, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), +/* 10 */ ACPI_OP("Local4", ARGP_LOCAL4, ARGI_LOCAL4, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), +/* 11 */ ACPI_OP("Local5", ARGP_LOCAL5, ARGI_LOCAL5, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), +/* 12 */ ACPI_OP("Local6", ARGP_LOCAL6, ARGI_LOCAL6, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), +/* 13 */ ACPI_OP("Local7", ARGP_LOCAL7, ARGI_LOCAL7, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), +/* 14 */ ACPI_OP("Arg0", ARGP_ARG0, ARGI_ARG0, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), +/* 15 */ ACPI_OP("Arg1", ARGP_ARG1, ARGI_ARG1, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), +/* 16 */ ACPI_OP("Arg2", ARGP_ARG2, ARGI_ARG2, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), +/* 17 */ ACPI_OP("Arg3", ARGP_ARG3, ARGI_ARG3, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), +/* 18 */ ACPI_OP("Arg4", ARGP_ARG4, ARGI_ARG4, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), +/* 19 */ ACPI_OP("Arg5", ARGP_ARG5, ARGI_ARG5, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), +/* 1A */ ACPI_OP("Arg6", ARGP_ARG6, ARGI_ARG6, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 3E */ ACPI_OP("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY, + AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), +/* 3F */ ACPI_OP("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY, + AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), +/* 40 */ ACPI_OP("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY, + AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), +/* 41 */ ACPI_OP("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY, + AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), +/* 42 */ ACPI_OP("Return", ARGP_RETURN_OP, ARGI_RETURN_OP, + ACPI_TYPE_ANY, AML_CLASS_CONTROL, + AML_TYPE_CONTROL, AML_HAS_ARGS), +/* 43 */ ACPI_OP("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY, + AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), +/* 44 */ ACPI_OP("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP, + ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), +/* 45 */ ACPI_OP("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER, + AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), + +/* Prefixed opcodes (Two-byte opcodes with a prefix op) */ + +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 55 */ ACPI_OP("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP, + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_CONSTANT, 0), +/* 56 */ ACPI_OP("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_CONSTANT, 0), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, + ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD | + AML_DEFER), + +/* Internal opcodes that map to invalid AML opcodes */ + +/* 60 */ ACPI_OP("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP, + ACPI_TYPE_ANY, AML_CLASS_INTERNAL, + AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), +/* 61 */ ACPI_OP("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP, + ACPI_TYPE_ANY, AML_CLASS_INTERNAL, + AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), +/* 62 */ ACPI_OP("LGreaterEqual", ARGP_LGREATEREQUAL_OP, + ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, + AML_HAS_ARGS | AML_CONSTANT), +/* 63 */ ACPI_OP("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP, + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE), +/* 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), +/* 65 */ ACPI_OP("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP, + ACPI_TYPE_ANY, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, 0), +/* 66 */ ACPI_OP("-ReservedField-", ARGP_RESERVEDFIELD_OP, + ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), +/* 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), +/* 68 */ ACPI_OP("-AccessField-", ARGP_ACCESSFIELD_OP, + ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), +/* 69 */ ACPI_OP("-StaticString", ARGP_STATICSTRING_OP, + ARGI_STATICSTRING_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), +/* 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), +/* 6B */ ACPI_OP("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID, + AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS), +/* 6C */ ACPI_OP("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, + AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS), +/* 6D */ ACPI_OP("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, + AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS), + +/* ACPI 2.0 opcodes */ + +/* 6E */ ACPI_OP("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), + /* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 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), +/* 7A */ ACPI_OP("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP, + ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), +/* 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), +/* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP, + ARGI_DATA_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), +/* 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), + +/* ACPI 3.0 opcodes */ + +/* 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) + +/*! [End] no source code translation !*/ +}; + +/* + * This table is directly indexed by the opcodes, and returns an + * index into the table above + */ +static const u8 acpi_gbl_short_op_index[256] = { +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, +/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, +/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, +/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D, +/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, +/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, +/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, +/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, +/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, +/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, +/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, +/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, +/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, +/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, +/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, +/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, +}; + +/* + * This table is indexed by the second opcode of the extended opcode + * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info) + */ +static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = { +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, +/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, +/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK, +/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, +/* 0x88 */ 0x7C, +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_opcode_info + * + * PARAMETERS: Opcode - The AML opcode + * + * RETURN: A pointer to the info about the opcode. + * + * DESCRIPTION: Find AML opcode description based on the opcode. + * NOTE: This procedure must ALWAYS return a valid pointer! + * + ******************************************************************************/ + +const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) +{ + ACPI_FUNCTION_NAME(ps_get_opcode_info); + + /* + * Detect normal 8-bit opcode or extended 16-bit opcode + */ + if (!(opcode & 0xFF00)) { + + /* Simple (8-bit) opcode: 0-255, can't index beyond table */ + + return (&acpi_gbl_aml_op_info + [acpi_gbl_short_op_index[(u8) opcode]]); + } + + if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) && + (((u8) opcode) <= MAX_EXTENDED_OPCODE)) { + + /* Valid extended (16-bit) opcode */ + + return (&acpi_gbl_aml_op_info + [acpi_gbl_long_op_index[(u8) opcode]]); + } + + /* Unknown AML opcode */ + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Unknown AML opcode [%4.4X]\n", opcode)); + + return (&acpi_gbl_aml_op_info[_UNK]); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_opcode_name + * + * PARAMETERS: Opcode - The AML opcode + * + * RETURN: A pointer to the name of the opcode (ASCII String) + * Note: Never returns NULL. + * + * DESCRIPTION: Translate an opcode into a human-readable string + * + ******************************************************************************/ + +char *acpi_ps_get_opcode_name(u16 opcode) +{ +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) + + const struct acpi_opcode_info *op; + + op = acpi_ps_get_opcode_info(opcode); + + /* Always guaranteed to return a valid pointer */ + + return (op->name); + +#else + return ("OpcodeName unavailable"); + +#endif +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_argument_count + * + * PARAMETERS: op_type - Type associated with the AML opcode + * + * RETURN: Argument count + * + * DESCRIPTION: Obtain the number of expected arguments for an AML opcode + * + ******************************************************************************/ + +u8 acpi_ps_get_argument_count(u32 op_type) +{ + + if (op_type <= AML_TYPE_EXEC_6A_0T_1R) { + return (acpi_gbl_argument_count[op_type]); + } + + return (0); +} diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c new file mode 100644 index 000000000000..9da48fdb811a --- /dev/null +++ b/drivers/acpi/acpica/psparse.c @@ -0,0 +1,701 @@ +/****************************************************************************** + * + * Module Name: psparse - Parser top level AML parse routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * Parse the AML and build an operation tree as most interpreters, + * like Perl, do. Parsing is done by hand rather than with a YACC + * generated parser to tightly constrain stack and dynamic memory + * usage. At the same time, parsing is kept flexible and the code + * fairly compact by parsing based on a list of AML opcode + * templates in aml_op_info[] + */ + +#include +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psparse") + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_opcode_size + * + * PARAMETERS: Opcode - An AML opcode + * + * RETURN: Size of the opcode, in bytes (1 or 2) + * + * DESCRIPTION: Get the size of the current opcode. + * + ******************************************************************************/ +u32 acpi_ps_get_opcode_size(u32 opcode) +{ + + /* Extended (2-byte) opcode if > 255 */ + + if (opcode > 0x00FF) { + return (2); + } + + /* Otherwise, just a single byte opcode */ + + return (1); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_peek_opcode + * + * PARAMETERS: parser_state - A parser state object + * + * RETURN: Next AML opcode + * + * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) + * + ******************************************************************************/ + +u16 acpi_ps_peek_opcode(struct acpi_parse_state * parser_state) +{ + u8 *aml; + u16 opcode; + + aml = parser_state->aml; + opcode = (u16) ACPI_GET8(aml); + + if (opcode == AML_EXTENDED_OP_PREFIX) { + + /* Extended opcode, get the second opcode byte */ + + aml++; + opcode = (u16) ((opcode << 8) | ACPI_GET8(aml)); + } + + return (opcode); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_complete_this_op + * + * PARAMETERS: walk_state - Current State + * Op - Op to complete + * + * RETURN: Status + * + * DESCRIPTION: Perform any cleanup at the completion of an Op. + * + ******************************************************************************/ + +acpi_status +acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, + union acpi_parse_object * op) +{ + union acpi_parse_object *prev; + union acpi_parse_object *next; + const struct acpi_opcode_info *parent_info; + union acpi_parse_object *replacement_op = NULL; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_PTR(ps_complete_this_op, op); + + /* Check for null Op, can happen if AML code is corrupt */ + + if (!op) { + return_ACPI_STATUS(AE_OK); /* OK for now */ + } + + /* Delete this op and the subtree below it if asked to */ + + if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != + ACPI_PARSE_DELETE_TREE) + || (walk_state->op_info->class == AML_CLASS_ARGUMENT)) { + return_ACPI_STATUS(AE_OK); + } + + /* Make sure that we only delete this subtree */ + + if (op->common.parent) { + prev = op->common.parent->common.value.arg; + if (!prev) { + + /* Nothing more to do */ + + goto cleanup; + } + + /* + * Check if we need to replace the operator and its subtree + * with a return value op (placeholder op) + */ + parent_info = + acpi_ps_get_opcode_info(op->common.parent->common. + aml_opcode); + + switch (parent_info->class) { + case AML_CLASS_CONTROL: + break; + + case AML_CLASS_CREATE: + + /* + * These opcodes contain term_arg operands. The current + * op must be replaced by a placeholder return op + */ + replacement_op = + acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); + if (!replacement_op) { + status = AE_NO_MEMORY; + } + break; + + case AML_CLASS_NAMED_OBJECT: + + /* + * These opcodes contain term_arg operands. The current + * op must be replaced by a placeholder return op + */ + if ((op->common.parent->common.aml_opcode == + AML_REGION_OP) + || (op->common.parent->common.aml_opcode == + AML_DATA_REGION_OP) + || (op->common.parent->common.aml_opcode == + AML_BUFFER_OP) + || (op->common.parent->common.aml_opcode == + AML_PACKAGE_OP) + || (op->common.parent->common.aml_opcode == + AML_BANK_FIELD_OP) + || (op->common.parent->common.aml_opcode == + AML_VAR_PACKAGE_OP)) { + replacement_op = + acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); + if (!replacement_op) { + status = AE_NO_MEMORY; + } + } else + if ((op->common.parent->common.aml_opcode == + AML_NAME_OP) + && (walk_state->pass_number <= + ACPI_IMODE_LOAD_PASS2)) { + if ((op->common.aml_opcode == AML_BUFFER_OP) + || (op->common.aml_opcode == AML_PACKAGE_OP) + || (op->common.aml_opcode == + AML_VAR_PACKAGE_OP)) { + replacement_op = + acpi_ps_alloc_op(op->common. + aml_opcode); + if (!replacement_op) { + status = AE_NO_MEMORY; + } else { + replacement_op->named.data = + op->named.data; + replacement_op->named.length = + op->named.length; + } + } + } + break; + + default: + + replacement_op = + acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); + if (!replacement_op) { + status = AE_NO_MEMORY; + } + } + + /* We must unlink this op from the parent tree */ + + if (prev == op) { + + /* This op is the first in the list */ + + if (replacement_op) { + replacement_op->common.parent = + op->common.parent; + replacement_op->common.value.arg = NULL; + replacement_op->common.node = op->common.node; + op->common.parent->common.value.arg = + replacement_op; + replacement_op->common.next = op->common.next; + } else { + op->common.parent->common.value.arg = + op->common.next; + } + } + + /* Search the parent list */ + + else + while (prev) { + + /* Traverse all siblings in the parent's argument list */ + + next = prev->common.next; + if (next == op) { + if (replacement_op) { + replacement_op->common.parent = + op->common.parent; + replacement_op->common.value. + arg = NULL; + replacement_op->common.node = + op->common.node; + prev->common.next = + replacement_op; + replacement_op->common.next = + op->common.next; + next = NULL; + } else { + prev->common.next = + op->common.next; + next = NULL; + } + } + prev = next; + } + } + + cleanup: + + /* Now we can actually delete the subtree rooted at Op */ + + acpi_ps_delete_parse_tree(op); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_next_parse_state + * + * PARAMETERS: walk_state - Current state + * Op - Current parse op + * callback_status - Status from previous operation + * + * RETURN: Status + * + * DESCRIPTION: Update the parser state based upon the return exception from + * the parser callback. + * + ******************************************************************************/ + +acpi_status +acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, + acpi_status callback_status) +{ + struct acpi_parse_state *parser_state = &walk_state->parser_state; + acpi_status status = AE_CTRL_PENDING; + + ACPI_FUNCTION_TRACE_PTR(ps_next_parse_state, op); + + switch (callback_status) { + case AE_CTRL_TERMINATE: + /* + * A control method was terminated via a RETURN statement. + * The walk of this method is complete. + */ + parser_state->aml = parser_state->aml_end; + status = AE_CTRL_TERMINATE; + break; + + case AE_CTRL_BREAK: + + parser_state->aml = walk_state->aml_last_while; + walk_state->control_state->common.value = FALSE; + status = AE_CTRL_BREAK; + break; + + case AE_CTRL_CONTINUE: + + parser_state->aml = walk_state->aml_last_while; + status = AE_CTRL_CONTINUE; + break; + + case AE_CTRL_PENDING: + + parser_state->aml = walk_state->aml_last_while; + break; + +#if 0 + case AE_CTRL_SKIP: + + parser_state->aml = parser_state->scope->parse_scope.pkg_end; + status = AE_OK; + break; +#endif + + case AE_CTRL_TRUE: + /* + * Predicate of an IF was true, and we are at the matching ELSE. + * Just close out this package + */ + parser_state->aml = acpi_ps_get_next_package_end(parser_state); + status = AE_CTRL_PENDING; + break; + + case AE_CTRL_FALSE: + /* + * Either an IF/WHILE Predicate was false or we encountered a BREAK + * opcode. In both cases, we do not execute the rest of the + * package; We simply close out the parent (finishing the walk of + * this branch of the tree) and continue execution at the parent + * level. + */ + parser_state->aml = parser_state->scope->parse_scope.pkg_end; + + /* In the case of a BREAK, just force a predicate (if any) to FALSE */ + + walk_state->control_state->common.value = FALSE; + status = AE_CTRL_END; + break; + + case AE_CTRL_TRANSFER: + + /* A method call (invocation) -- transfer control */ + + status = AE_CTRL_TRANSFER; + walk_state->prev_op = op; + walk_state->method_call_op = op; + walk_state->method_call_node = + (op->common.value.arg)->common.node; + + /* Will return value (if any) be used by the caller? */ + + walk_state->return_used = + acpi_ds_is_result_used(op, walk_state); + break; + + default: + + status = callback_status; + if ((callback_status & AE_CODE_MASK) == AE_CODE_CONTROL) { + status = AE_OK; + } + break; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_parse_aml + * + * PARAMETERS: walk_state - Current state + * + * + * RETURN: Status + * + * DESCRIPTION: Parse raw AML and return a tree of ops + * + ******************************************************************************/ + +acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) +{ + acpi_status status; + struct acpi_thread_state *thread; + struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list; + struct acpi_walk_state *previous_walk_state; + + ACPI_FUNCTION_TRACE(ps_parse_aml); + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Entered with WalkState=%p Aml=%p size=%X\n", + walk_state, walk_state->parser_state.aml, + walk_state->parser_state.aml_size)); + + if (!walk_state->parser_state.aml) { + return_ACPI_STATUS(AE_NULL_OBJECT); + } + + /* Create and initialize a new thread state */ + + thread = acpi_ut_create_thread_state(); + if (!thread) { + if (walk_state->method_desc) { + + /* Executing a control method - additional cleanup */ + + acpi_ds_terminate_control_method( + walk_state->method_desc, walk_state); + } + + acpi_ds_delete_walk_state(walk_state); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + walk_state->thread = thread; + + /* + * If executing a method, the starting sync_level is this method's + * sync_level + */ + if (walk_state->method_desc) { + walk_state->thread->current_sync_level = + walk_state->method_desc->method.sync_level; + } + + acpi_ds_push_walk_state(walk_state, thread); + + /* + * This global allows the AML debugger to get a handle to the currently + * executing control method. + */ + acpi_gbl_current_walk_list = thread; + + /* + * Execute the walk loop as long as there is a valid Walk State. This + * handles nested control method invocations without recursion. + */ + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "State=%p\n", walk_state)); + + status = AE_OK; + while (walk_state) { + if (ACPI_SUCCESS(status)) { + /* + * The parse_loop executes AML until the method terminates + * or calls another method. + */ + status = acpi_ps_parse_loop(walk_state); + } + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Completed one call to walk loop, %s State=%p\n", + acpi_format_exception(status), walk_state)); + + if (status == AE_CTRL_TRANSFER) { + /* + * A method call was detected. + * Transfer control to the called control method + */ + status = + acpi_ds_call_control_method(thread, walk_state, + NULL); + if (ACPI_FAILURE(status)) { + status = + acpi_ds_method_error(status, walk_state); + } + + /* + * If the transfer to the new method method call worked, a new walk + * state was created -- get it + */ + walk_state = acpi_ds_get_current_walk_state(thread); + continue; + } else if (status == AE_CTRL_TERMINATE) { + status = AE_OK; + } else if ((status != AE_OK) && (walk_state->method_desc)) { + + /* Either the method parse or actual execution failed */ + + ACPI_ERROR_METHOD("Method parse/execution failed", + walk_state->method_node, NULL, + status); + + /* Check for possible multi-thread reentrancy problem */ + + if ((status == AE_ALREADY_EXISTS) && + (!walk_state->method_desc->method.mutex)) { + ACPI_INFO((AE_INFO, + "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", + walk_state->method_node->name. + ascii)); + + /* + * Method tried to create an object twice. The probable cause is + * that the method cannot handle reentrancy. + * + * The method is marked not_serialized, but it tried to create + * a named object, causing the second thread entrance to fail. + * Workaround this problem by marking the method permanently + * as Serialized. + */ + walk_state->method_desc->method.method_flags |= + AML_METHOD_SERIALIZED; + walk_state->method_desc->method.sync_level = 0; + } + } + + /* We are done with this walk, move on to the parent if any */ + + walk_state = acpi_ds_pop_walk_state(thread); + + /* Reset the current scope to the beginning of scope stack */ + + acpi_ds_scope_stack_clear(walk_state); + + /* + * If we just returned from the execution of a control method or if we + * encountered an error during the method parse phase, there's lots of + * cleanup to do + */ + if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == + ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) { + acpi_ds_terminate_control_method(walk_state-> + method_desc, + walk_state); + } + + /* Delete this walk state and all linked control states */ + + acpi_ps_cleanup_scope(&walk_state->parser_state); + previous_walk_state = walk_state; + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "ReturnValue=%p, ImplicitValue=%p State=%p\n", + walk_state->return_desc, + walk_state->implicit_return_obj, walk_state)); + + /* Check if we have restarted a preempted walk */ + + walk_state = acpi_ds_get_current_walk_state(thread); + if (walk_state) { + if (ACPI_SUCCESS(status)) { + /* + * There is another walk state, restart it. + * If the method return value is not used by the parent, + * The object is deleted + */ + if (!previous_walk_state->return_desc) { + /* + * In slack mode execution, if there is no return value + * we should implicitly return zero (0) as a default value. + */ + if (acpi_gbl_enable_interpreter_slack && + !previous_walk_state-> + implicit_return_obj) { + previous_walk_state-> + implicit_return_obj = + acpi_ut_create_internal_object + (ACPI_TYPE_INTEGER); + if (!previous_walk_state-> + implicit_return_obj) { + return_ACPI_STATUS + (AE_NO_MEMORY); + } + + previous_walk_state-> + implicit_return_obj-> + integer.value = 0; + } + + /* Restart the calling control method */ + + status = + acpi_ds_restart_control_method + (walk_state, + previous_walk_state-> + implicit_return_obj); + } else { + /* + * We have a valid return value, delete any implicit + * return value. + */ + acpi_ds_clear_implicit_return + (previous_walk_state); + + status = + acpi_ds_restart_control_method + (walk_state, + previous_walk_state->return_desc); + } + if (ACPI_SUCCESS(status)) { + walk_state->walk_type |= + ACPI_WALK_METHOD_RESTART; + } + } else { + /* On error, delete any return object or implicit return */ + + acpi_ut_remove_reference(previous_walk_state-> + return_desc); + acpi_ds_clear_implicit_return + (previous_walk_state); + } + } + + /* + * Just completed a 1st-level method, save the final internal return + * value (if any) + */ + else if (previous_walk_state->caller_return_desc) { + if (previous_walk_state->implicit_return_obj) { + *(previous_walk_state->caller_return_desc) = + previous_walk_state->implicit_return_obj; + } else { + /* NULL if no return value */ + + *(previous_walk_state->caller_return_desc) = + previous_walk_state->return_desc; + } + } else { + if (previous_walk_state->return_desc) { + + /* Caller doesn't want it, must delete it */ + + acpi_ut_remove_reference(previous_walk_state-> + return_desc); + } + if (previous_walk_state->implicit_return_obj) { + + /* Caller doesn't want it, must delete it */ + + acpi_ut_remove_reference(previous_walk_state-> + implicit_return_obj); + } + } + + acpi_ds_delete_walk_state(previous_walk_state); + } + + /* Normal exit */ + + acpi_ex_release_all_mutexes(thread); + acpi_ut_delete_generic_state(ACPI_CAST_PTR + (union acpi_generic_state, thread)); + acpi_gbl_current_walk_list = prev_walk_list; + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/psscope.c b/drivers/acpi/acpica/psscope.c new file mode 100644 index 000000000000..22929ca1ffe4 --- /dev/null +++ b/drivers/acpi/acpica/psscope.c @@ -0,0 +1,265 @@ +/****************************************************************************** + * + * Module Name: psscope - Parser scope stack management routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psscope") + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_parent_scope + * + * PARAMETERS: parser_state - Current parser state object + * + * RETURN: Pointer to an Op object + * + * DESCRIPTION: Get parent of current op being parsed + * + ******************************************************************************/ +union acpi_parse_object *acpi_ps_get_parent_scope(struct acpi_parse_state + *parser_state) +{ + + return (parser_state->scope->parse_scope.op); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_has_completed_scope + * + * PARAMETERS: parser_state - Current parser state object + * + * RETURN: Boolean, TRUE = scope completed. + * + * DESCRIPTION: Is parsing of current argument complete? Determined by + * 1) AML pointer is at or beyond the end of the scope + * 2) The scope argument count has reached zero. + * + ******************************************************************************/ + +u8 acpi_ps_has_completed_scope(struct acpi_parse_state * parser_state) +{ + + return ((u8) + ((parser_state->aml >= parser_state->scope->parse_scope.arg_end + || !parser_state->scope->parse_scope.arg_count))); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_init_scope + * + * PARAMETERS: parser_state - Current parser state object + * Root - the Root Node of this new scope + * + * RETURN: Status + * + * DESCRIPTION: Allocate and init a new scope object + * + ******************************************************************************/ + +acpi_status +acpi_ps_init_scope(struct acpi_parse_state * parser_state, + union acpi_parse_object * root_op) +{ + union acpi_generic_state *scope; + + ACPI_FUNCTION_TRACE_PTR(ps_init_scope, root_op); + + scope = acpi_ut_create_generic_state(); + if (!scope) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_RPSCOPE; + scope->parse_scope.op = root_op; + scope->parse_scope.arg_count = ACPI_VAR_ARGS; + scope->parse_scope.arg_end = parser_state->aml_end; + scope->parse_scope.pkg_end = parser_state->aml_end; + + parser_state->scope = scope; + parser_state->start_op = root_op; + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_push_scope + * + * PARAMETERS: parser_state - Current parser state object + * Op - Current op to be pushed + * remaining_args - List of args remaining + * arg_count - Fixed or variable number of args + * + * RETURN: Status + * + * DESCRIPTION: Push current op to begin parsing its argument + * + ******************************************************************************/ + +acpi_status +acpi_ps_push_scope(struct acpi_parse_state *parser_state, + union acpi_parse_object *op, + u32 remaining_args, u32 arg_count) +{ + union acpi_generic_state *scope; + + ACPI_FUNCTION_TRACE_PTR(ps_push_scope, op); + + scope = acpi_ut_create_generic_state(); + if (!scope) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_PSCOPE; + scope->parse_scope.op = op; + scope->parse_scope.arg_list = remaining_args; + scope->parse_scope.arg_count = arg_count; + scope->parse_scope.pkg_end = parser_state->pkg_end; + + /* Push onto scope stack */ + + acpi_ut_push_generic_state(&parser_state->scope, scope); + + if (arg_count == ACPI_VAR_ARGS) { + + /* Multiple arguments */ + + scope->parse_scope.arg_end = parser_state->pkg_end; + } else { + /* Single argument */ + + scope->parse_scope.arg_end = ACPI_TO_POINTER(ACPI_MAX_PTR); + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_pop_scope + * + * PARAMETERS: parser_state - Current parser state object + * Op - Where the popped op is returned + * arg_list - Where the popped "next argument" is + * returned + * arg_count - Count of objects in arg_list + * + * RETURN: Status + * + * DESCRIPTION: Return to parsing a previous op + * + ******************************************************************************/ + +void +acpi_ps_pop_scope(struct acpi_parse_state *parser_state, + union acpi_parse_object **op, u32 * arg_list, u32 * arg_count) +{ + union acpi_generic_state *scope = parser_state->scope; + + ACPI_FUNCTION_TRACE(ps_pop_scope); + + /* Only pop the scope if there is in fact a next scope */ + + if (scope->common.next) { + scope = acpi_ut_pop_generic_state(&parser_state->scope); + + /* Return to parsing previous op */ + + *op = scope->parse_scope.op; + *arg_list = scope->parse_scope.arg_list; + *arg_count = scope->parse_scope.arg_count; + parser_state->pkg_end = scope->parse_scope.pkg_end; + + /* All done with this scope state structure */ + + acpi_ut_delete_generic_state(scope); + } else { + /* Empty parse stack, prepare to fetch next opcode */ + + *op = NULL; + *arg_list = 0; + *arg_count = 0; + } + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Popped Op %p Args %X\n", *op, *arg_count)); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_cleanup_scope + * + * PARAMETERS: parser_state - Current parser state object + * + * RETURN: None + * + * DESCRIPTION: Destroy available list, remaining stack levels, and return + * root scope + * + ******************************************************************************/ + +void acpi_ps_cleanup_scope(struct acpi_parse_state *parser_state) +{ + union acpi_generic_state *scope; + + ACPI_FUNCTION_TRACE_PTR(ps_cleanup_scope, parser_state); + + if (!parser_state) { + return_VOID; + } + + /* Delete anything on the scope stack */ + + while (parser_state->scope) { + scope = acpi_ut_pop_generic_state(&parser_state->scope); + acpi_ut_delete_generic_state(scope); + } + + return_VOID; +} diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c new file mode 100644 index 000000000000..8e73fbf00971 --- /dev/null +++ b/drivers/acpi/acpica/pstree.c @@ -0,0 +1,312 @@ +/****************************************************************************** + * + * Module Name: pstree - Parser op tree manipulation/traversal/search + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("pstree") + +/* Local prototypes */ +#ifdef ACPI_OBSOLETE_FUNCTIONS +union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op); +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_arg + * + * PARAMETERS: Op - Get an argument for this op + * Argn - Nth argument to get + * + * RETURN: The argument (as an Op object). NULL if argument does not exist + * + * DESCRIPTION: Get the specified op's argument. + * + ******************************************************************************/ + +union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn) +{ + union acpi_parse_object *arg = NULL; + const struct acpi_opcode_info *op_info; + + ACPI_FUNCTION_ENTRY(); + + /* Get the info structure for this opcode */ + + op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); + if (op_info->class == AML_CLASS_UNKNOWN) { + + /* Invalid opcode or ASCII character */ + + return (NULL); + } + + /* Check if this opcode requires argument sub-objects */ + + if (!(op_info->flags & AML_HAS_ARGS)) { + + /* Has no linked argument objects */ + + return (NULL); + } + + /* Get the requested argument object */ + + arg = op->common.value.arg; + while (arg && argn) { + argn--; + arg = arg->common.next; + } + + return (arg); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_append_arg + * + * PARAMETERS: Op - Append an argument to this Op. + * Arg - Argument Op to append + * + * RETURN: None. + * + * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK) + * + ******************************************************************************/ + +void +acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) +{ + union acpi_parse_object *prev_arg; + const struct acpi_opcode_info *op_info; + + ACPI_FUNCTION_ENTRY(); + + if (!op) { + return; + } + + /* Get the info structure for this opcode */ + + op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); + if (op_info->class == AML_CLASS_UNKNOWN) { + + /* Invalid opcode */ + + ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X", + op->common.aml_opcode)); + return; + } + + /* Check if this opcode requires argument sub-objects */ + + if (!(op_info->flags & AML_HAS_ARGS)) { + + /* Has no linked argument objects */ + + return; + } + + /* Append the argument to the linked argument list */ + + if (op->common.value.arg) { + + /* Append to existing argument list */ + + prev_arg = op->common.value.arg; + while (prev_arg->common.next) { + prev_arg = prev_arg->common.next; + } + prev_arg->common.next = arg; + } else { + /* No argument list, this will be the first argument */ + + op->common.value.arg = arg; + } + + /* Set the parent in this arg and any args linked after it */ + + while (arg) { + arg->common.parent = op; + arg = arg->common.next; + + op->common.arg_list_length++; + } +} + +#ifdef ACPI_FUTURE_USAGE +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_depth_next + * + * PARAMETERS: Origin - Root of subtree to search + * Op - Last (previous) Op that was found + * + * RETURN: Next Op found in the search. + * + * DESCRIPTION: Get next op in tree (walking the tree in depth-first order) + * Return NULL when reaching "origin" or when walking up from root + * + ******************************************************************************/ + +union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin, + union acpi_parse_object *op) +{ + union acpi_parse_object *next = NULL; + union acpi_parse_object *parent; + union acpi_parse_object *arg; + + ACPI_FUNCTION_ENTRY(); + + if (!op) { + return (NULL); + } + + /* Look for an argument or child */ + + next = acpi_ps_get_arg(op, 0); + if (next) { + return (next); + } + + /* Look for a sibling */ + + next = op->common.next; + if (next) { + return (next); + } + + /* Look for a sibling of parent */ + + parent = op->common.parent; + + while (parent) { + arg = acpi_ps_get_arg(parent, 0); + while (arg && (arg != origin) && (arg != op)) { + arg = arg->common.next; + } + + if (arg == origin) { + + /* Reached parent of origin, end search */ + + return (NULL); + } + + if (parent->common.next) { + + /* Found sibling of parent */ + + return (parent->common.next); + } + + op = parent; + parent = parent->common.parent; + } + + return (next); +} + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_child + * + * PARAMETERS: Op - Get the child of this Op + * + * RETURN: Child Op, Null if none is found. + * + * DESCRIPTION: Get op's children or NULL if none + * + ******************************************************************************/ + +union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op) +{ + union acpi_parse_object *child = NULL; + + ACPI_FUNCTION_ENTRY(); + + switch (op->common.aml_opcode) { + case AML_SCOPE_OP: + case AML_ELSE_OP: + case AML_DEVICE_OP: + case AML_THERMAL_ZONE_OP: + case AML_INT_METHODCALL_OP: + + child = acpi_ps_get_arg(op, 0); + break; + + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_METHOD_OP: + case AML_IF_OP: + case AML_WHILE_OP: + case AML_FIELD_OP: + + child = acpi_ps_get_arg(op, 1); + break; + + case AML_POWER_RES_OP: + case AML_INDEX_FIELD_OP: + + child = acpi_ps_get_arg(op, 2); + break; + + case AML_PROCESSOR_OP: + case AML_BANK_FIELD_OP: + + child = acpi_ps_get_arg(op, 3); + break; + + default: + /* All others have no children */ + break; + } + + return (child); +} +#endif +#endif /* ACPI_FUTURE_USAGE */ diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c new file mode 100644 index 000000000000..eec7d624db8e --- /dev/null +++ b/drivers/acpi/acpica/psutils.c @@ -0,0 +1,244 @@ +/****************************************************************************** + * + * Module Name: psutils - Parser miscellaneous utilities (Parser only) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psutils") + +/******************************************************************************* + * + * FUNCTION: acpi_ps_create_scope_op + * + * PARAMETERS: None + * + * RETURN: A new Scope object, null on failure + * + * DESCRIPTION: Create a Scope and associated namepath op with the root name + * + ******************************************************************************/ +union acpi_parse_object *acpi_ps_create_scope_op(void) +{ + union acpi_parse_object *scope_op; + + scope_op = acpi_ps_alloc_op(AML_SCOPE_OP); + if (!scope_op) { + return (NULL); + } + + scope_op->named.name = ACPI_ROOT_NAME; + return (scope_op); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_init_op + * + * PARAMETERS: Op - A newly allocated Op object + * Opcode - Opcode to store in the Op + * + * RETURN: None + * + * DESCRIPTION: Initialize a parse (Op) object + * + ******************************************************************************/ + +void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode) +{ + ACPI_FUNCTION_ENTRY(); + + op->common.descriptor_type = ACPI_DESC_TYPE_PARSER; + op->common.aml_opcode = opcode; + + ACPI_DISASM_ONLY_MEMBERS(ACPI_STRNCPY(op->common.aml_op_name, + (acpi_ps_get_opcode_info + (opcode))->name, + sizeof(op->common.aml_op_name))); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_alloc_op + * + * PARAMETERS: Opcode - Opcode that will be stored in the new Op + * + * RETURN: Pointer to the new Op, null on failure + * + * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on + * opcode. A cache of opcodes is available for the pure + * GENERIC_OP, since this is by far the most commonly used. + * + ******************************************************************************/ + +union acpi_parse_object *acpi_ps_alloc_op(u16 opcode) +{ + union acpi_parse_object *op; + const struct acpi_opcode_info *op_info; + u8 flags = ACPI_PARSEOP_GENERIC; + + ACPI_FUNCTION_ENTRY(); + + op_info = acpi_ps_get_opcode_info(opcode); + + /* Determine type of parse_op required */ + + if (op_info->flags & AML_DEFER) { + flags = ACPI_PARSEOP_DEFERRED; + } else if (op_info->flags & AML_NAMED) { + flags = ACPI_PARSEOP_NAMED; + } else if (opcode == AML_INT_BYTELIST_OP) { + flags = ACPI_PARSEOP_BYTELIST; + } + + /* Allocate the minimum required size object */ + + if (flags == ACPI_PARSEOP_GENERIC) { + + /* The generic op (default) is by far the most common (16 to 1) */ + + op = acpi_os_acquire_object(acpi_gbl_ps_node_cache); + } else { + /* Extended parseop */ + + op = acpi_os_acquire_object(acpi_gbl_ps_node_ext_cache); + } + + /* Initialize the Op */ + + if (op) { + acpi_ps_init_op(op, opcode); + op->common.flags = flags; + } + + return (op); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_free_op + * + * PARAMETERS: Op - Op to be freed + * + * RETURN: None. + * + * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list + * or actually free it. + * + ******************************************************************************/ + +void acpi_ps_free_op(union acpi_parse_object *op) +{ + ACPI_FUNCTION_NAME(ps_free_op); + + if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n", + op)); + } + + if (op->common.flags & ACPI_PARSEOP_GENERIC) { + (void)acpi_os_release_object(acpi_gbl_ps_node_cache, op); + } else { + (void)acpi_os_release_object(acpi_gbl_ps_node_ext_cache, op); + } +} + +/******************************************************************************* + * + * FUNCTION: Utility functions + * + * DESCRIPTION: Low level character and object functions + * + ******************************************************************************/ + +/* + * Is "c" a namestring lead character? + */ +u8 acpi_ps_is_leading_char(u32 c) +{ + return ((u8) (c == '_' || (c >= 'A' && c <= 'Z'))); +} + +/* + * Is "c" a namestring prefix character? + */ +u8 acpi_ps_is_prefix_char(u32 c) +{ + return ((u8) (c == '\\' || c == '^')); +} + +/* + * Get op's name (4-byte name segment) or 0 if unnamed + */ +#ifdef ACPI_FUTURE_USAGE +u32 acpi_ps_get_name(union acpi_parse_object * op) +{ + + /* The "generic" object has no name associated with it */ + + if (op->common.flags & ACPI_PARSEOP_GENERIC) { + return (0); + } + + /* Only the "Extended" parse objects have a name */ + + return (op->named.name); +} +#endif /* ACPI_FUTURE_USAGE */ + +/* + * Set op's name + */ +void acpi_ps_set_name(union acpi_parse_object *op, u32 name) +{ + + /* The "generic" object has no name associated with it */ + + if (op->common.flags & ACPI_PARSEOP_GENERIC) { + return; + } + + op->named.name = name; +} diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c new file mode 100644 index 000000000000..dacc4228ba1a --- /dev/null +++ b/drivers/acpi/acpica/pswalk.c @@ -0,0 +1,110 @@ +/****************************************************************************** + * + * Module Name: pswalk - Parser routines to walk parsed op tree(s) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("pswalk") + +/******************************************************************************* + * + * FUNCTION: acpi_ps_delete_parse_tree + * + * PARAMETERS: subtree_root - Root of tree (or subtree) to delete + * + * RETURN: None + * + * DESCRIPTION: Delete a portion of or an entire parse tree. + * + ******************************************************************************/ +void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root) +{ + union acpi_parse_object *op = subtree_root; + union acpi_parse_object *next = NULL; + union acpi_parse_object *parent = NULL; + + ACPI_FUNCTION_TRACE_PTR(ps_delete_parse_tree, subtree_root); + + /* Visit all nodes in the subtree */ + + while (op) { + + /* Check if we are not ascending */ + + if (op != parent) { + + /* Look for an argument or child of the current op */ + + next = acpi_ps_get_arg(op, 0); + if (next) { + + /* Still going downward in tree (Op is not completed yet) */ + + op = next; + continue; + } + } + + /* No more children, this Op is complete. */ + + next = op->common.next; + parent = op->common.parent; + + acpi_ps_free_op(op); + + /* If we are back to the starting point, the walk is complete. */ + + if (op == subtree_root) { + return_VOID; + } + if (next) { + op = next; + } else { + op = parent; + } + } + + return_VOID; +} diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c new file mode 100644 index 000000000000..98c31a893706 --- /dev/null +++ b/drivers/acpi/acpica/psxface.c @@ -0,0 +1,385 @@ +/****************************************************************************** + * + * Module Name: psxface - Parser external interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psxface") + +/* Local Prototypes */ +static void acpi_ps_start_trace(struct acpi_evaluate_info *info); + +static void acpi_ps_stop_trace(struct acpi_evaluate_info *info); + +static void +acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action); + +/******************************************************************************* + * + * FUNCTION: acpi_debug_trace + * + * PARAMETERS: method_name - Valid ACPI name string + * debug_level - Optional level mask. 0 to use default + * debug_layer - Optional layer mask. 0 to use default + * Flags - bit 1: one shot(1) or persistent(0) + * + * RETURN: Status + * + * DESCRIPTION: External interface to enable debug tracing during control + * method execution + * + ******************************************************************************/ + +acpi_status +acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags) +{ + acpi_status status; + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* TBDs: Validate name, allow full path or just nameseg */ + + acpi_gbl_trace_method_name = *ACPI_CAST_PTR(u32, name); + acpi_gbl_trace_flags = flags; + + if (debug_level) { + acpi_gbl_trace_dbg_level = debug_level; + } + if (debug_layer) { + acpi_gbl_trace_dbg_layer = debug_layer; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_start_trace + * + * PARAMETERS: Info - Method info struct + * + * RETURN: None + * + * DESCRIPTION: Start control method execution trace + * + ******************************************************************************/ + +static void acpi_ps_start_trace(struct acpi_evaluate_info *info) +{ + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return; + } + + if ((!acpi_gbl_trace_method_name) || + (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { + goto exit; + } + + acpi_gbl_original_dbg_level = acpi_dbg_level; + acpi_gbl_original_dbg_layer = acpi_dbg_layer; + + acpi_dbg_level = 0x00FFFFFF; + acpi_dbg_layer = ACPI_UINT32_MAX; + + if (acpi_gbl_trace_dbg_level) { + acpi_dbg_level = acpi_gbl_trace_dbg_level; + } + if (acpi_gbl_trace_dbg_layer) { + acpi_dbg_layer = acpi_gbl_trace_dbg_layer; + } + + exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_stop_trace + * + * PARAMETERS: Info - Method info struct + * + * RETURN: None + * + * DESCRIPTION: Stop control method execution trace + * + ******************************************************************************/ + +static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) +{ + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return; + } + + if ((!acpi_gbl_trace_method_name) || + (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { + goto exit; + } + + /* Disable further tracing if type is one-shot */ + + if (acpi_gbl_trace_flags & 1) { + acpi_gbl_trace_method_name = 0; + acpi_gbl_trace_dbg_level = 0; + acpi_gbl_trace_dbg_layer = 0; + } + + acpi_dbg_level = acpi_gbl_original_dbg_level; + acpi_dbg_layer = acpi_gbl_original_dbg_layer; + + exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_execute_method + * + * PARAMETERS: Info - Method info block, contains: + * Node - Method Node to execute + * obj_desc - Method object + * Parameters - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * parameter_type - Type of Parameter list + * return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * pass_number - Parse or execute pass + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method + * + ******************************************************************************/ + +acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) +{ + acpi_status status; + union acpi_parse_object *op; + struct acpi_walk_state *walk_state; + + ACPI_FUNCTION_TRACE(ps_execute_method); + + /* Validate the Info and method Node */ + + if (!info || !info->resolved_node) { + return_ACPI_STATUS(AE_NULL_ENTRY); + } + + /* Init for new method, wait on concurrency semaphore */ + + status = + acpi_ds_begin_method_execution(info->resolved_node, info->obj_desc, + NULL); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * The caller "owns" the parameters, so give each one an extra reference + */ + acpi_ps_update_parameter_list(info, REF_INCREMENT); + + /* Begin tracing if requested */ + + acpi_ps_start_trace(info); + + /* + * Execute the method. Performs parse simultaneously + */ + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n", + info->resolved_node->name.ascii, info->resolved_node, + info->obj_desc)); + + /* Create and init a Root Node */ + + op = acpi_ps_create_scope_op(); + if (!op) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Create and initialize a new walk state */ + + info->pass_number = ACPI_IMODE_EXECUTE; + walk_state = + acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL, + NULL, NULL); + if (!walk_state) { + status = AE_NO_MEMORY; + goto cleanup; + } + + status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node, + info->obj_desc->method.aml_start, + info->obj_desc->method.aml_length, info, + info->pass_number); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } + + /* Invoke an internal method if necessary */ + + if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { + status = info->obj_desc->method.implementation(walk_state); + info->return_object = walk_state->return_desc; + + /* Cleanup states */ + + acpi_ds_scope_stack_clear(walk_state); + acpi_ps_cleanup_scope(&walk_state->parser_state); + acpi_ds_terminate_control_method(walk_state->method_desc, + walk_state); + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } + + /* + * Start method evaluation with an implicit return of zero. + * This is done for Windows compatibility. + */ + if (acpi_gbl_enable_interpreter_slack) { + walk_state->implicit_return_obj = + acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!walk_state->implicit_return_obj) { + status = AE_NO_MEMORY; + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } + + walk_state->implicit_return_obj->integer.value = 0; + } + + /* Parse the AML */ + + status = acpi_ps_parse_aml(walk_state); + + /* walk_state was deleted by parse_aml */ + + cleanup: + acpi_ps_delete_parse_tree(op); + + /* End optional tracing */ + + acpi_ps_stop_trace(info); + + /* Take away the extra reference that we gave the parameters above */ + + acpi_ps_update_parameter_list(info, REF_DECREMENT); + + /* Exit now if error above */ + + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * If the method has returned an object, signal this to the caller with + * a control exception code + */ + if (info->return_object) { + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n", + info->return_object)); + ACPI_DUMP_STACK_ENTRY(info->return_object); + + status = AE_CTRL_RETURN_VALUE; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_update_parameter_list + * + * PARAMETERS: Info - See struct acpi_evaluate_info + * (Used: parameter_type and Parameters) + * Action - Add or Remove reference + * + * RETURN: Status + * + * DESCRIPTION: Update reference count on all method parameter objects + * + ******************************************************************************/ + +static void +acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action) +{ + u32 i; + + if (info->parameters) { + + /* Update reference count for each parameter */ + + for (i = 0; info->parameters[i]; i++) { + + /* Ignore errors, just do them all */ + + (void)acpi_ut_update_object_reference(info-> + parameters[i], + action); + } + } +} diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c new file mode 100644 index 000000000000..b4aba3aebcb8 --- /dev/null +++ b/drivers/acpi/acpica/rsaddr.c @@ -0,0 +1,381 @@ +/******************************************************************************* + * + * Module Name: rsaddr - Address resource descriptors (16/32/64) + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsaddr") + +/******************************************************************************* + * + * acpi_rs_convert_address16 - All WORD (16-bit) address resources + * + ******************************************************************************/ +struct acpi_rsconvert_info acpi_rs_convert_address16[5] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS16, + ACPI_RS_SIZE(struct acpi_resource_address16), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address16)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS16, + sizeof(struct aml_resource_address16), + 0}, + + /* Resource Type, General Flags, and Type-Specific Flags */ + + {ACPI_RSC_ADDRESS, 0, 0, 0}, + + /* + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + */ + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.address16.granularity), + AML_OFFSET(address16.granularity), + 5}, + + /* Optional resource_source (Index and String) */ + + {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address16.resource_source), + 0, + sizeof(struct aml_resource_address16)} +}; + +/******************************************************************************* + * + * acpi_rs_convert_address32 - All DWORD (32-bit) address resources + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_address32[5] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS32, + ACPI_RS_SIZE(struct acpi_resource_address32), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address32)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS32, + sizeof(struct aml_resource_address32), + 0}, + + /* Resource Type, General Flags, and Type-Specific Flags */ + + {ACPI_RSC_ADDRESS, 0, 0, 0}, + + /* + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + */ + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.address32.granularity), + AML_OFFSET(address32.granularity), + 5}, + + /* Optional resource_source (Index and String) */ + + {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address32.resource_source), + 0, + sizeof(struct aml_resource_address32)} +}; + +/******************************************************************************* + * + * acpi_rs_convert_address64 - All QWORD (64-bit) address resources + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_address64[5] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS64, + ACPI_RS_SIZE(struct acpi_resource_address64), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address64)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS64, + sizeof(struct aml_resource_address64), + 0}, + + /* Resource Type, General Flags, and Type-Specific Flags */ + + {ACPI_RSC_ADDRESS, 0, 0, 0}, + + /* + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + */ + {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.address64.granularity), + AML_OFFSET(address64.granularity), + 5}, + + /* Optional resource_source (Index and String) */ + + {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address64.resource_source), + 0, + sizeof(struct aml_resource_address64)} +}; + +/******************************************************************************* + * + * acpi_rs_convert_ext_address64 - All Extended (64-bit) address resources + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_ext_address64[5] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64, + ACPI_RS_SIZE(struct acpi_resource_extended_address64), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_address64)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64, + sizeof(struct aml_resource_extended_address64), + 0}, + + /* Resource Type, General Flags, and Type-Specific Flags */ + + {ACPI_RSC_ADDRESS, 0, 0, 0}, + + /* Revision ID */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.ext_address64.revision_iD), + AML_OFFSET(ext_address64.revision_iD), + 1}, + /* + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + * Type-Specific Attribute + */ + {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.ext_address64.granularity), + AML_OFFSET(ext_address64.granularity), + 6} +}; + +/******************************************************************************* + * + * acpi_rs_convert_general_flags - Flags common to all address descriptors + * + ******************************************************************************/ + +static struct acpi_rsconvert_info acpi_rs_convert_general_flags[6] = { + {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.flags), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_general_flags)}, + + /* Resource Type (Memory, Io, bus_number, etc.) */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.address.resource_type), + AML_OFFSET(address.resource_type), + 1}, + + /* General Flags - Consume, Decode, min_fixed, max_fixed */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.producer_consumer), + AML_OFFSET(address.flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.decode), + AML_OFFSET(address.flags), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.min_address_fixed), + AML_OFFSET(address.flags), + 2}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.max_address_fixed), + AML_OFFSET(address.flags), + 3} +}; + +/******************************************************************************* + * + * acpi_rs_convert_mem_flags - Flags common to Memory address descriptors + * + ******************************************************************************/ + +static struct acpi_rsconvert_info acpi_rs_convert_mem_flags[5] = { + {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_mem_flags)}, + + /* Memory-specific flags */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.write_protect), + AML_OFFSET(address.specific_flags), + 0}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.caching), + AML_OFFSET(address.specific_flags), + 1}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.range_type), + AML_OFFSET(address.specific_flags), + 3}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.translation), + AML_OFFSET(address.specific_flags), + 5} +}; + +/******************************************************************************* + * + * acpi_rs_convert_io_flags - Flags common to I/O address descriptors + * + ******************************************************************************/ + +static struct acpi_rsconvert_info acpi_rs_convert_io_flags[4] = { + {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io_flags)}, + + /* I/O-specific flags */ + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.io.range_type), + AML_OFFSET(address.specific_flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.io.translation), + AML_OFFSET(address.specific_flags), + 4}, + + {ACPI_RSC_1BITFLAG, + ACPI_RS_OFFSET(data.address.info.io.translation_type), + AML_OFFSET(address.specific_flags), + 5} +}; + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_address_common + * + * PARAMETERS: Resource - Pointer to the internal resource struct + * Aml - Pointer to the AML resource descriptor + * + * RETURN: TRUE if the resource_type field is OK, FALSE otherwise + * + * DESCRIPTION: Convert common flag fields from a raw AML resource descriptor + * to an internal resource descriptor + * + ******************************************************************************/ + +u8 +acpi_rs_get_address_common(struct acpi_resource *resource, + union aml_resource *aml) +{ + ACPI_FUNCTION_ENTRY(); + + /* Validate the Resource Type */ + + if ((aml->address.resource_type > 2) + && (aml->address.resource_type < 0xC0)) { + return (FALSE); + } + + /* Get the Resource Type and General Flags */ + + (void)acpi_rs_convert_aml_to_resource(resource, aml, + acpi_rs_convert_general_flags); + + /* Get the Type-Specific Flags (Memory and I/O descriptors only) */ + + if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) { + (void)acpi_rs_convert_aml_to_resource(resource, aml, + acpi_rs_convert_mem_flags); + } else if (resource->data.address.resource_type == ACPI_IO_RANGE) { + (void)acpi_rs_convert_aml_to_resource(resource, aml, + acpi_rs_convert_io_flags); + } else { + /* Generic resource type, just grab the type_specific byte */ + + resource->data.address.info.type_specific = + aml->address.specific_flags; + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_set_address_common + * + * PARAMETERS: Aml - Pointer to the AML resource descriptor + * Resource - Pointer to the internal resource struct + * + * RETURN: None + * + * DESCRIPTION: Convert common flag fields from a resource descriptor to an + * AML descriptor + * + ******************************************************************************/ + +void +acpi_rs_set_address_common(union aml_resource *aml, + struct acpi_resource *resource) +{ + ACPI_FUNCTION_ENTRY(); + + /* Set the Resource Type and General Flags */ + + (void)acpi_rs_convert_resource_to_aml(resource, aml, + acpi_rs_convert_general_flags); + + /* Set the Type-Specific Flags (Memory and I/O descriptors only) */ + + if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) { + (void)acpi_rs_convert_resource_to_aml(resource, aml, + acpi_rs_convert_mem_flags); + } else if (resource->data.address.resource_type == ACPI_IO_RANGE) { + (void)acpi_rs_convert_resource_to_aml(resource, aml, + acpi_rs_convert_io_flags); + } else { + /* Generic resource type, just copy the type_specific byte */ + + aml->address.specific_flags = + resource->data.address.info.type_specific; + } +} diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c new file mode 100644 index 000000000000..4f2b186fe302 --- /dev/null +++ b/drivers/acpi/acpica/rscalc.c @@ -0,0 +1,618 @@ +/******************************************************************************* + * + * Module Name: rscalc - Calculate stream and list lengths + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rscalc") + +/* Local prototypes */ +static u8 acpi_rs_count_set_bits(u16 bit_field); + +static acpi_rs_length +acpi_rs_struct_option_length(struct acpi_resource_source *resource_source); + +static u32 +acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length); + +/******************************************************************************* + * + * FUNCTION: acpi_rs_count_set_bits + * + * PARAMETERS: bit_field - Field in which to count bits + * + * RETURN: Number of bits set within the field + * + * DESCRIPTION: Count the number of bits set in a resource field. Used for + * (Short descriptor) interrupt and DMA lists. + * + ******************************************************************************/ + +static u8 acpi_rs_count_set_bits(u16 bit_field) +{ + u8 bits_set; + + ACPI_FUNCTION_ENTRY(); + + for (bits_set = 0; bit_field; bits_set++) { + + /* Zero the least significant bit that is set */ + + bit_field &= (u16) (bit_field - 1); + } + + return bits_set; +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_struct_option_length + * + * PARAMETERS: resource_source - Pointer to optional descriptor field + * + * RETURN: Status + * + * DESCRIPTION: Common code to handle optional resource_source_index and + * resource_source fields in some Large descriptors. Used during + * list-to-stream conversion + * + ******************************************************************************/ + +static acpi_rs_length +acpi_rs_struct_option_length(struct acpi_resource_source *resource_source) +{ + ACPI_FUNCTION_ENTRY(); + + /* + * If the resource_source string is valid, return the size of the string + * (string_length includes the NULL terminator) plus the size of the + * resource_source_index (1). + */ + if (resource_source->string_ptr) { + return ((acpi_rs_length) (resource_source->string_length + 1)); + } + + return (0); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_stream_option_length + * + * PARAMETERS: resource_length - Length from the resource header + * minimum_total_length - Minimum length of this resource, before + * any optional fields. Includes header size + * + * RETURN: Length of optional string (0 if no string present) + * + * DESCRIPTION: Common code to handle optional resource_source_index and + * resource_source fields in some Large descriptors. Used during + * stream-to-list conversion + * + ******************************************************************************/ + +static u32 +acpi_rs_stream_option_length(u32 resource_length, + u32 minimum_aml_resource_length) +{ + u32 string_length = 0; + + ACPI_FUNCTION_ENTRY(); + + /* + * The resource_source_index and resource_source are optional elements of some + * Large-type resource descriptors. + */ + + /* + * If the length of the actual resource descriptor is greater than the ACPI + * spec-defined minimum length, it means that a resource_source_index exists + * and is followed by a (required) null terminated string. The string length + * (including the null terminator) is the resource length minus the minimum + * length, minus one byte for the resource_source_index itself. + */ + if (resource_length > minimum_aml_resource_length) { + + /* Compute the length of the optional string */ + + string_length = + resource_length - minimum_aml_resource_length - 1; + } + + /* + * Round the length up to a multiple of the native word in order to + * guarantee that the entire resource descriptor is native word aligned + */ + return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_aml_length + * + * PARAMETERS: Resource - Pointer to the resource linked list + * size_needed - Where the required size is returned + * + * RETURN: Status + * + * DESCRIPTION: Takes a linked list of internal resource descriptors and + * calculates the size buffer needed to hold the corresponding + * external resource byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) +{ + acpi_size aml_size_needed = 0; + acpi_rs_length total_size; + + ACPI_FUNCTION_TRACE(rs_get_aml_length); + + /* Traverse entire list of internal resource descriptors */ + + while (resource) { + + /* Validate the descriptor type */ + + if (resource->type > ACPI_RESOURCE_TYPE_MAX) { + return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); + } + + /* Get the base size of the (external stream) resource descriptor */ + + total_size = acpi_gbl_aml_resource_sizes[resource->type]; + + /* + * Augment the base size for descriptors with optional and/or + * variable-length fields + */ + switch (resource->type) { + case ACPI_RESOURCE_TYPE_IRQ: + + /* Length can be 3 or 2 */ + + if (resource->data.irq.descriptor_length == 2) { + total_size--; + } + break; + + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + + /* Length can be 1 or 0 */ + + if (resource->data.irq.descriptor_length == 0) { + total_size--; + } + break; + + case ACPI_RESOURCE_TYPE_VENDOR: + /* + * Vendor Defined Resource: + * For a Vendor Specific resource, if the Length is between 1 and 7 + * it will be created as a Small Resource data type, otherwise it + * is a Large Resource data type. + */ + if (resource->data.vendor.byte_length > 7) { + + /* Base size of a Large resource descriptor */ + + total_size = + sizeof(struct aml_resource_large_header); + } + + /* Add the size of the vendor-specific data */ + + total_size = (acpi_rs_length) + (total_size + resource->data.vendor.byte_length); + break; + + case ACPI_RESOURCE_TYPE_END_TAG: + /* + * End Tag: + * We are done -- return the accumulated total size. + */ + *size_needed = aml_size_needed + total_size; + + /* Normal exit */ + + return_ACPI_STATUS(AE_OK); + + case ACPI_RESOURCE_TYPE_ADDRESS16: + /* + * 16-Bit Address Resource: + * Add the size of the optional resource_source info + */ + total_size = (acpi_rs_length) + (total_size + + acpi_rs_struct_option_length(&resource->data. + address16. + resource_source)); + break; + + case ACPI_RESOURCE_TYPE_ADDRESS32: + /* + * 32-Bit Address Resource: + * Add the size of the optional resource_source info + */ + total_size = (acpi_rs_length) + (total_size + + acpi_rs_struct_option_length(&resource->data. + address32. + resource_source)); + break; + + case ACPI_RESOURCE_TYPE_ADDRESS64: + /* + * 64-Bit Address Resource: + * Add the size of the optional resource_source info + */ + total_size = (acpi_rs_length) + (total_size + + acpi_rs_struct_option_length(&resource->data. + address64. + resource_source)); + break; + + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + /* + * Extended IRQ Resource: + * Add the size of each additional optional interrupt beyond the + * required 1 (4 bytes for each u32 interrupt number) + */ + total_size = (acpi_rs_length) + (total_size + + ((resource->data.extended_irq.interrupt_count - + 1) * 4) + + /* Add the size of the optional resource_source info */ + acpi_rs_struct_option_length(&resource->data. + extended_irq. + resource_source)); + break; + + default: + break; + } + + /* Update the total */ + + aml_size_needed += total_size; + + /* Point to the next object */ + + resource = + ACPI_ADD_PTR(struct acpi_resource, resource, + resource->length); + } + + /* Did not find an end_tag resource descriptor */ + + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_list_length + * + * PARAMETERS: aml_buffer - Pointer to the resource byte stream + * aml_buffer_length - Size of aml_buffer + * size_needed - Where the size needed is returned + * + * RETURN: Status + * + * DESCRIPTION: Takes an external resource byte stream and calculates the size + * buffer needed to hold the corresponding internal resource + * descriptor linked list. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_list_length(u8 * aml_buffer, + u32 aml_buffer_length, acpi_size * size_needed) +{ + acpi_status status; + u8 *end_aml; + u8 *buffer; + u32 buffer_size; + u16 temp16; + u16 resource_length; + u32 extra_struct_bytes; + u8 resource_index; + u8 minimum_aml_resource_length; + + ACPI_FUNCTION_TRACE(rs_get_list_length); + + *size_needed = 0; + end_aml = aml_buffer + aml_buffer_length; + + /* Walk the list of AML resource descriptors */ + + while (aml_buffer < end_aml) { + + /* Validate the Resource Type and Resource Length */ + + status = acpi_ut_validate_resource(aml_buffer, &resource_index); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the resource length and base (minimum) AML size */ + + resource_length = acpi_ut_get_resource_length(aml_buffer); + minimum_aml_resource_length = + acpi_gbl_resource_aml_sizes[resource_index]; + + /* + * Augment the size for descriptors with optional + * and/or variable length fields + */ + extra_struct_bytes = 0; + buffer = + aml_buffer + acpi_ut_get_resource_header_length(aml_buffer); + + switch (acpi_ut_get_resource_type(aml_buffer)) { + case ACPI_RESOURCE_NAME_IRQ: + /* + * IRQ Resource: + * Get the number of bits set in the 16-bit IRQ mask + */ + ACPI_MOVE_16_TO_16(&temp16, buffer); + extra_struct_bytes = acpi_rs_count_set_bits(temp16); + break; + + case ACPI_RESOURCE_NAME_DMA: + /* + * DMA Resource: + * Get the number of bits set in the 8-bit DMA mask + */ + extra_struct_bytes = acpi_rs_count_set_bits(*buffer); + break; + + case ACPI_RESOURCE_NAME_VENDOR_SMALL: + case ACPI_RESOURCE_NAME_VENDOR_LARGE: + /* + * Vendor Resource: + * Get the number of vendor data bytes + */ + extra_struct_bytes = resource_length; + break; + + case ACPI_RESOURCE_NAME_END_TAG: + /* + * End Tag: + * This is the normal exit, add size of end_tag + */ + *size_needed += ACPI_RS_SIZE_MIN; + return_ACPI_STATUS(AE_OK); + + case ACPI_RESOURCE_NAME_ADDRESS32: + case ACPI_RESOURCE_NAME_ADDRESS16: + case ACPI_RESOURCE_NAME_ADDRESS64: + /* + * Address Resource: + * Add the size of the optional resource_source + */ + extra_struct_bytes = + acpi_rs_stream_option_length(resource_length, + minimum_aml_resource_length); + break; + + case ACPI_RESOURCE_NAME_EXTENDED_IRQ: + /* + * Extended IRQ Resource: + * Using the interrupt_table_length, add 4 bytes for each additional + * interrupt. Note: at least one interrupt is required and is + * included in the minimum descriptor size (reason for the -1) + */ + extra_struct_bytes = (buffer[1] - 1) * sizeof(u32); + + /* Add the size of the optional resource_source */ + + extra_struct_bytes += + acpi_rs_stream_option_length(resource_length - + extra_struct_bytes, + minimum_aml_resource_length); + break; + + default: + break; + } + + /* + * Update the required buffer size for the internal descriptor structs + * + * Important: Round the size up for the appropriate alignment. This + * is a requirement on IA64. + */ + buffer_size = acpi_gbl_resource_struct_sizes[resource_index] + + extra_struct_bytes; + buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size); + + *size_needed += buffer_size; + + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, + "Type %.2X, AmlLength %.2X InternalLength %.2X\n", + acpi_ut_get_resource_type(aml_buffer), + acpi_ut_get_descriptor_length(aml_buffer), + buffer_size)); + + /* + * Point to the next resource within the AML stream using the length + * contained in the resource descriptor header + */ + aml_buffer += acpi_ut_get_descriptor_length(aml_buffer); + } + + /* Did not find an end_tag resource descriptor */ + + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_pci_routing_table_length + * + * PARAMETERS: package_object - Pointer to the package object + * buffer_size_needed - u32 pointer of the size buffer + * needed to properly return the + * parsed data + * + * RETURN: Status + * + * DESCRIPTION: Given a package representing a PCI routing table, this + * calculates the size of the corresponding linked list of + * descriptions. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, + acpi_size * buffer_size_needed) +{ + u32 number_of_elements; + acpi_size temp_size_needed = 0; + union acpi_operand_object **top_object_list; + u32 index; + union acpi_operand_object *package_element; + union acpi_operand_object **sub_object_list; + u8 name_found; + u32 table_index; + + ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length); + + number_of_elements = package_object->package.count; + + /* + * Calculate the size of the return buffer. + * The base size is the number of elements * the sizes of the + * structures. Additional space for the strings is added below. + * The minus one is to subtract the size of the u8 Source[1] + * member because it is added below. + * + * But each PRT_ENTRY structure has a pointer to a string and + * the size of that string must be found. + */ + top_object_list = package_object->package.elements; + + for (index = 0; index < number_of_elements; index++) { + + /* Dereference the sub-package */ + + package_element = *top_object_list; + + /* + * The sub_object_list will now point to an array of the + * four IRQ elements: Address, Pin, Source and source_index + */ + sub_object_list = package_element->package.elements; + + /* Scan the irq_table_elements for the Source Name String */ + + name_found = FALSE; + + for (table_index = 0; table_index < 4 && !name_found; + table_index++) { + if (*sub_object_list && /* Null object allowed */ + ((ACPI_TYPE_STRING == + ACPI_GET_OBJECT_TYPE(*sub_object_list)) || + ((ACPI_TYPE_LOCAL_REFERENCE == + ACPI_GET_OBJECT_TYPE(*sub_object_list)) && + ((*sub_object_list)->reference.class == + ACPI_REFCLASS_NAME)))) { + name_found = TRUE; + } else { + /* Look at the next element */ + + sub_object_list++; + } + } + + temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4); + + /* Was a String type found? */ + + if (name_found) { + if (ACPI_GET_OBJECT_TYPE(*sub_object_list) == + ACPI_TYPE_STRING) { + /* + * The length String.Length field does not include the + * terminating NULL, add 1 + */ + temp_size_needed += ((acpi_size) + (*sub_object_list)->string. + length + 1); + } else { + temp_size_needed += + acpi_ns_get_pathname_length((*sub_object_list)->reference.node); + if (!temp_size_needed) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + } + } else { + /* + * If no name was found, then this is a NULL, which is + * translated as a u32 zero. + */ + temp_size_needed += sizeof(u32); + } + + /* Round up the size since each element must be aligned */ + + temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed); + + /* Point to the next union acpi_operand_object */ + + top_object_list++; + } + + /* + * Add an extra element to the end of the list, essentially a + * NULL terminator + */ + *buffer_size_needed = + temp_size_needed + sizeof(struct acpi_pci_routing_table); + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c new file mode 100644 index 000000000000..3ca606974d51 --- /dev/null +++ b/drivers/acpi/acpica/rscreate.c @@ -0,0 +1,468 @@ +/******************************************************************************* + * + * Module Name: rscreate - Create resource lists/tables + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rscreate") + +/******************************************************************************* + * + * FUNCTION: acpi_rs_create_resource_list + * + * PARAMETERS: aml_buffer - Pointer to the resource byte stream + * output_buffer - Pointer to the user's buffer + * + * RETURN: Status: AE_OK if okay, else a valid acpi_status code + * If output_buffer is not large enough, output_buffer_length + * indicates how large output_buffer should be, else it + * indicates how may u8 elements of output_buffer are valid. + * + * DESCRIPTION: Takes the byte stream returned from a _CRS, _PRS control method + * execution and parses the stream to create a linked list + * of device resources. + * + ******************************************************************************/ +acpi_status +acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, + struct acpi_buffer *output_buffer) +{ + + acpi_status status; + u8 *aml_start; + acpi_size list_size_needed = 0; + u32 aml_buffer_length; + void *resource; + + ACPI_FUNCTION_TRACE(rs_create_resource_list); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlBuffer = %p\n", aml_buffer)); + + /* Params already validated, so we don't re-validate here */ + + aml_buffer_length = aml_buffer->buffer.length; + aml_start = aml_buffer->buffer.pointer; + + /* + * Pass the aml_buffer into a module that can calculate + * the buffer size needed for the linked list + */ + status = acpi_rs_get_list_length(aml_start, aml_buffer_length, + &list_size_needed); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X ListSizeNeeded=%X\n", + status, (u32) list_size_needed)); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer(output_buffer, list_size_needed); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Do the conversion */ + + resource = output_buffer->pointer; + status = acpi_ut_walk_aml_resources(aml_start, aml_buffer_length, + acpi_rs_convert_aml_to_resources, + &resource); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", + output_buffer->pointer, (u32) output_buffer->length)); + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_create_pci_routing_table + * + * PARAMETERS: package_object - Pointer to an union acpi_operand_object + * package + * output_buffer - Pointer to the user's buffer + * + * RETURN: Status AE_OK if okay, else a valid acpi_status code. + * If the output_buffer is too small, the error will be + * AE_BUFFER_OVERFLOW and output_buffer->Length will point + * to the size buffer needed. + * + * DESCRIPTION: Takes the union acpi_operand_object package and creates a + * linked list of PCI interrupt descriptions + * + * NOTE: It is the caller's responsibility to ensure that the start of the + * output buffer is aligned properly (if necessary). + * + ******************************************************************************/ + +acpi_status +acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, + struct acpi_buffer *output_buffer) +{ + u8 *buffer; + union acpi_operand_object **top_object_list; + union acpi_operand_object **sub_object_list; + union acpi_operand_object *obj_desc; + acpi_size buffer_size_needed = 0; + u32 number_of_elements; + u32 index; + struct acpi_pci_routing_table *user_prt; + struct acpi_namespace_node *node; + acpi_status status; + struct acpi_buffer path_buffer; + + ACPI_FUNCTION_TRACE(rs_create_pci_routing_table); + + /* Params already validated, so we don't re-validate here */ + + /* Get the required buffer length */ + + status = acpi_rs_get_pci_routing_table_length(package_object, + &buffer_size_needed); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "BufferSizeNeeded = %X\n", + (u32) buffer_size_needed)); + + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer(output_buffer, buffer_size_needed); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Loop through the ACPI_INTERNAL_OBJECTS - Each object should be a + * package that in turn contains an acpi_integer Address, a u8 Pin, + * a Name, and a u8 source_index. + */ + top_object_list = package_object->package.elements; + number_of_elements = package_object->package.count; + buffer = output_buffer->pointer; + user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer); + + for (index = 0; index < number_of_elements; index++) { + int source_name_index = 2; + int source_index_index = 3; + + /* + * Point user_prt past this current structure + * + * NOTE: On the first iteration, user_prt->Length will + * be zero because we cleared the return buffer earlier + */ + buffer += user_prt->length; + user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer); + + /* + * Fill in the Length field with the information we have at this point. + * The minus four is to subtract the size of the u8 Source[4] member + * because it is added below. + */ + user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4); + + /* Each element of the top-level package must also be a package */ + + if (ACPI_GET_OBJECT_TYPE(*top_object_list) != ACPI_TYPE_PACKAGE) { + ACPI_ERROR((AE_INFO, + "(PRT[%X]) Need sub-package, found %s", + index, + acpi_ut_get_object_type_name + (*top_object_list))); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + /* Each sub-package must be of length 4 */ + + if ((*top_object_list)->package.count != 4) { + ACPI_ERROR((AE_INFO, + "(PRT[%X]) Need package of length 4, found length %d", + index, (*top_object_list)->package.count)); + return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT); + } + + /* + * Dereference the sub-package. + * The sub_object_list will now point to an array of the four IRQ + * elements: [Address, Pin, Source, source_index] + */ + sub_object_list = (*top_object_list)->package.elements; + + /* 1) First subobject: Dereference the PRT.Address */ + + obj_desc = sub_object_list[0]; + if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + ACPI_ERROR((AE_INFO, + "(PRT[%X].Address) Need Integer, found %s", + index, + acpi_ut_get_object_type_name(obj_desc))); + return_ACPI_STATUS(AE_BAD_DATA); + } + + user_prt->address = obj_desc->integer.value; + + /* 2) Second subobject: Dereference the PRT.Pin */ + + obj_desc = sub_object_list[1]; + if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + ACPI_ERROR((AE_INFO, + "(PRT[%X].Pin) Need Integer, found %s", + index, + acpi_ut_get_object_type_name(obj_desc))); + return_ACPI_STATUS(AE_BAD_DATA); + } + + /* + * If BIOS erroneously reversed the _PRT source_name and source_index, + * then reverse them back. + */ + if (ACPI_GET_OBJECT_TYPE(sub_object_list[3]) != + ACPI_TYPE_INTEGER) { + if (acpi_gbl_enable_interpreter_slack) { + source_name_index = 3; + source_index_index = 2; + printk(KERN_WARNING + "ACPI: Handling Garbled _PRT entry\n"); + } else { + ACPI_ERROR((AE_INFO, + "(PRT[%X].source_index) Need Integer, found %s", + index, + acpi_ut_get_object_type_name + (sub_object_list[3]))); + return_ACPI_STATUS(AE_BAD_DATA); + } + } + + user_prt->pin = (u32) obj_desc->integer.value; + + /* + * If the BIOS has erroneously reversed the _PRT source_name (index 2) + * and the source_index (index 3), fix it. _PRT is important enough to + * workaround this BIOS error. This also provides compatibility with + * other ACPI implementations. + */ + obj_desc = sub_object_list[3]; + if (!obj_desc + || (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { + sub_object_list[3] = sub_object_list[2]; + sub_object_list[2] = obj_desc; + + ACPI_WARNING((AE_INFO, + "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed", + index)); + } + + /* + * 3) Third subobject: Dereference the PRT.source_name + * The name may be unresolved (slack mode), so allow a null object + */ + obj_desc = sub_object_list[source_name_index]; + if (obj_desc) { + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_LOCAL_REFERENCE: + + if (obj_desc->reference.class != + ACPI_REFCLASS_NAME) { + ACPI_ERROR((AE_INFO, + "(PRT[%X].Source) Need name, found Reference Class %X", + index, + obj_desc->reference.class)); + return_ACPI_STATUS(AE_BAD_DATA); + } + + node = obj_desc->reference.node; + + /* Use *remaining* length of the buffer as max for pathname */ + + path_buffer.length = output_buffer->length - + (u32) ((u8 *) user_prt->source - + (u8 *) output_buffer->pointer); + path_buffer.pointer = user_prt->source; + + status = + acpi_ns_handle_to_pathname((acpi_handle) + node, + &path_buffer); + + /* +1 to include null terminator */ + + user_prt->length += + (u32) ACPI_STRLEN(user_prt->source) + 1; + break; + + case ACPI_TYPE_STRING: + + ACPI_STRCPY(user_prt->source, + obj_desc->string.pointer); + + /* + * Add to the Length field the length of the string + * (add 1 for terminator) + */ + user_prt->length += obj_desc->string.length + 1; + break; + + case ACPI_TYPE_INTEGER: + /* + * If this is a number, then the Source Name is NULL, since the + * entire buffer was zeroed out, we can leave this alone. + * + * Add to the Length field the length of the u32 NULL + */ + user_prt->length += sizeof(u32); + break; + + default: + + ACPI_ERROR((AE_INFO, + "(PRT[%X].Source) Need Ref/String/Integer, found %s", + index, + acpi_ut_get_object_type_name + (obj_desc))); + return_ACPI_STATUS(AE_BAD_DATA); + } + } + + /* Now align the current length */ + + user_prt->length = + (u32) ACPI_ROUND_UP_TO_64BIT(user_prt->length); + + /* 4) Fourth subobject: Dereference the PRT.source_index */ + + obj_desc = sub_object_list[source_index_index]; + if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + ACPI_ERROR((AE_INFO, + "(PRT[%X].SourceIndex) Need Integer, found %s", + index, + acpi_ut_get_object_type_name(obj_desc))); + return_ACPI_STATUS(AE_BAD_DATA); + } + + user_prt->source_index = (u32) obj_desc->integer.value; + + /* Point to the next union acpi_operand_object in the top level package */ + + top_object_list++; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", + output_buffer->pointer, (u32) output_buffer->length)); + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_create_aml_resources + * + * PARAMETERS: linked_list_buffer - Pointer to the resource linked list + * output_buffer - Pointer to the user's buffer + * + * RETURN: Status AE_OK if okay, else a valid acpi_status code. + * If the output_buffer is too small, the error will be + * AE_BUFFER_OVERFLOW and output_buffer->Length will point + * to the size buffer needed. + * + * DESCRIPTION: Takes the linked list of device resources and + * creates a bytestream to be used as input for the + * _SRS control method. + * + ******************************************************************************/ + +acpi_status +acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, + struct acpi_buffer *output_buffer) +{ + acpi_status status; + acpi_size aml_size_needed = 0; + + ACPI_FUNCTION_TRACE(rs_create_aml_resources); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "LinkedListBuffer = %p\n", + linked_list_buffer)); + + /* + * Params already validated, so we don't re-validate here + * + * Pass the linked_list_buffer into a module that calculates + * the buffer size needed for the byte stream. + */ + status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n", + (u32) aml_size_needed, + acpi_format_exception(status))); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer(output_buffer, aml_size_needed); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Do the conversion */ + + status = + acpi_rs_convert_resources_to_aml(linked_list_buffer, + aml_size_needed, + output_buffer->pointer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", + output_buffer->pointer, (u32) output_buffer->length)); + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c new file mode 100644 index 000000000000..936a59be39fa --- /dev/null +++ b/drivers/acpi/acpica/rsdump.c @@ -0,0 +1,771 @@ +/******************************************************************************* + * + * Module Name: rsdump - Functions to display the resource structures. + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsdump") +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/* Local prototypes */ +static void acpi_rs_out_string(char *title, char *value); + +static void acpi_rs_out_integer8(char *title, u8 value); + +static void acpi_rs_out_integer16(char *title, u16 value); + +static void acpi_rs_out_integer32(char *title, u32 value); + +static void acpi_rs_out_integer64(char *title, u64 value); + +static void acpi_rs_out_title(char *title); + +static void acpi_rs_dump_byte_list(u16 length, u8 * data); + +static void acpi_rs_dump_dword_list(u8 length, u32 * data); + +static void acpi_rs_dump_short_byte_list(u8 length, u8 * data); + +static void +acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source); + +static void acpi_rs_dump_address_common(union acpi_resource_data *resource); + +static void +acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table); + +#define ACPI_RSD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_resource_data,f) +#define ACPI_PRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f) +#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_rsdump_info)) + +/******************************************************************************* + * + * Resource Descriptor info tables + * + * Note: The first table entry must be a Title or Literal and must contain + * the table length (number of table entries) + * + ******************************************************************************/ + +struct acpi_rsdump_info acpi_rs_dump_irq[7] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length), + "Descriptor Length", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", + acpi_gbl_he_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", + acpi_gbl_ll_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing", + acpi_gbl_shr_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count), + "Interrupt Count", NULL}, + {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]), + "Interrupt List", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_dma[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed", + acpi_gbl_typ_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering", + acpi_gbl_bm_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type", + acpi_gbl_siz_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count", + NULL}, + {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), + "Start-Dependent-Functions", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length), + "Descriptor Length", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), + "Compatibility Priority", acpi_gbl_config_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), + "Performance/Robustness", acpi_gbl_config_decode} +}; + +struct acpi_rsdump_info acpi_rs_dump_end_dpf[1] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_dpf), + "End-Dependent-Functions", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_io[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io), "I/O", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(io.io_decode), "Address Decoding", + acpi_gbl_io_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.alignment), "Alignment", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.address_length), "Address Length", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_io[3] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_io), + "Fixed I/O", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_io.address), "Address", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_io.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_vendor[3] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_vendor), + "Vendor Specific", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(vendor.byte_length), "Length", NULL}, + {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET(vendor.byte_data[0]), "Vendor Data", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory24[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24), + "24-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.alignment), "Alignment", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory32[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32), + "32-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.alignment), "Alignment", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32), + "32-Bit Fixed Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address16[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16), + "16-Bit WORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address32[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32), + "32-Bit DWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address64[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64), + "64-Bit QWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64), + "64-Bit Extended Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity), + "Granularity", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum), + "Address Minimum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum), + "Address Maximum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length), + "Address Length", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific), + "Type-Specific Attribute", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_irq), + "Extended IRQ", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer), + "Type", acpi_gbl_consume_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering), + "Triggering", acpi_gbl_he_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity", + acpi_gbl_ll_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing", + acpi_gbl_shr_decode}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL, + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count), + "Interrupt Count", NULL}, + {ACPI_RSD_DWORDLIST, ACPI_RSD_OFFSET(extended_irq.interrupts[0]), + "Interrupt List", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_generic_reg), + "Generic Register", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.space_id), "Space ID", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_width), "Bit Width", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_offset), "Bit Offset", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.access_size), + "Access Size", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL} +}; + +/* + * Tables used for common address descriptor flag fields + */ +static struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_general_flags), NULL, + NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer), + "Consumer/Producer", acpi_gbl_consume_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode", + acpi_gbl_dec_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed), + "Min Relocatability", acpi_gbl_min_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed), + "Max Relocatability", acpi_gbl_max_decode} +}; + +static struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = { + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags), + "Resource Type", (void *)"Memory Range"}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching), + "Caching", acpi_gbl_mem_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type), + "Range Type", acpi_gbl_mtp_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation), + "Translation", acpi_gbl_ttp_decode} +}; + +static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = { + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags), + "Resource Type", (void *)"I/O Range"}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type), + "Range Type", acpi_gbl_rng_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation), + "Translation", acpi_gbl_ttp_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type), + "Translation Type", acpi_gbl_trs_decode} +}; + +/* + * Table used to dump _PRT contents + */ +static struct acpi_rsdump_info acpi_rs_dump_prt[5] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_prt), NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_PRT_OFFSET(address), "Address", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(pin), "Pin", NULL}, + {ACPI_RSD_STRING, ACPI_PRT_OFFSET(source[0]), "Source", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(source_index), "Source Index", NULL} +}; + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_descriptor + * + * PARAMETERS: Resource + * + * RETURN: None + * + * DESCRIPTION: + * + ******************************************************************************/ + +static void +acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) +{ + u8 *target = NULL; + u8 *previous_target; + char *name; + u8 count; + + /* First table entry must contain the table length (# of table entries) */ + + count = table->offset; + + while (count) { + previous_target = target; + target = ACPI_ADD_PTR(u8, resource, table->offset); + name = table->name; + + switch (table->opcode) { + case ACPI_RSD_TITLE: + /* + * Optional resource title + */ + if (table->name) { + acpi_os_printf("%s Resource\n", name); + } + break; + + /* Strings */ + + case ACPI_RSD_LITERAL: + acpi_rs_out_string(name, + ACPI_CAST_PTR(char, table->pointer)); + break; + + case ACPI_RSD_STRING: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, target)); + break; + + /* Data items, 8/16/32/64 bit */ + + case ACPI_RSD_UINT8: + acpi_rs_out_integer8(name, ACPI_GET8(target)); + break; + + case ACPI_RSD_UINT16: + acpi_rs_out_integer16(name, ACPI_GET16(target)); + break; + + case ACPI_RSD_UINT32: + acpi_rs_out_integer32(name, ACPI_GET32(target)); + break; + + case ACPI_RSD_UINT64: + acpi_rs_out_integer64(name, ACPI_GET64(target)); + break; + + /* Flags: 1-bit and 2-bit flags supported */ + + case ACPI_RSD_1BITFLAG: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, + table-> + pointer[*target & + 0x01])); + break; + + case ACPI_RSD_2BITFLAG: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, + table-> + pointer[*target & + 0x03])); + break; + + case ACPI_RSD_SHORTLIST: + /* + * Short byte list (single line output) for DMA and IRQ resources + * Note: The list length is obtained from the previous table entry + */ + if (previous_target) { + acpi_rs_out_title(name); + acpi_rs_dump_short_byte_list(*previous_target, + target); + } + break; + + case ACPI_RSD_LONGLIST: + /* + * Long byte list for Vendor resource data + * Note: The list length is obtained from the previous table entry + */ + if (previous_target) { + acpi_rs_dump_byte_list(ACPI_GET16 + (previous_target), + target); + } + break; + + case ACPI_RSD_DWORDLIST: + /* + * Dword list for Extended Interrupt resources + * Note: The list length is obtained from the previous table entry + */ + if (previous_target) { + acpi_rs_dump_dword_list(*previous_target, + ACPI_CAST_PTR(u32, + target)); + } + break; + + case ACPI_RSD_ADDRESS: + /* + * Common flags for all Address resources + */ + acpi_rs_dump_address_common(ACPI_CAST_PTR + (union acpi_resource_data, + target)); + break; + + case ACPI_RSD_SOURCE: + /* + * Optional resource_source for Address resources + */ + acpi_rs_dump_resource_source(ACPI_CAST_PTR(struct + acpi_resource_source, + target)); + break; + + default: + acpi_os_printf("**** Invalid table opcode [%X] ****\n", + table->opcode); + return; + } + + table++; + count--; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_resource_source + * + * PARAMETERS: resource_source - Pointer to a Resource Source struct + * + * RETURN: None + * + * DESCRIPTION: Common routine for dumping the optional resource_source and the + * corresponding resource_source_index. + * + ******************************************************************************/ + +static void +acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source) +{ + ACPI_FUNCTION_ENTRY(); + + if (resource_source->index == 0xFF) { + return; + } + + acpi_rs_out_integer8("Resource Source Index", resource_source->index); + + acpi_rs_out_string("Resource Source", + resource_source->string_ptr ? + resource_source->string_ptr : "[Not Specified]"); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_address_common + * + * PARAMETERS: Resource - Pointer to an internal resource descriptor + * + * RETURN: None + * + * DESCRIPTION: Dump the fields that are common to all Address resource + * descriptors + * + ******************************************************************************/ + +static void acpi_rs_dump_address_common(union acpi_resource_data *resource) +{ + ACPI_FUNCTION_ENTRY(); + + /* Decode the type-specific flags */ + + switch (resource->address.resource_type) { + case ACPI_MEMORY_RANGE: + + acpi_rs_dump_descriptor(resource, acpi_rs_dump_memory_flags); + break; + + case ACPI_IO_RANGE: + + acpi_rs_dump_descriptor(resource, acpi_rs_dump_io_flags); + break; + + case ACPI_BUS_NUMBER_RANGE: + + acpi_rs_out_string("Resource Type", "Bus Number Range"); + break; + + default: + + acpi_rs_out_integer8("Resource Type", + (u8) resource->address.resource_type); + break; + } + + /* Decode the general flags */ + + acpi_rs_dump_descriptor(resource, acpi_rs_dump_general_flags); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_resource_list + * + * PARAMETERS: resource_list - Pointer to a resource descriptor list + * + * RETURN: None + * + * DESCRIPTION: Dispatches the structure to the correct dump routine. + * + ******************************************************************************/ + +void acpi_rs_dump_resource_list(struct acpi_resource *resource_list) +{ + u32 count = 0; + u32 type; + + ACPI_FUNCTION_ENTRY(); + + if (!(acpi_dbg_level & ACPI_LV_RESOURCES) + || !(_COMPONENT & acpi_dbg_layer)) { + return; + } + + /* Walk list and dump all resource descriptors (END_TAG terminates) */ + + do { + acpi_os_printf("\n[%02X] ", count); + count++; + + /* Validate Type before dispatch */ + + type = resource_list->type; + if (type > ACPI_RESOURCE_TYPE_MAX) { + acpi_os_printf + ("Invalid descriptor type (%X) in resource list\n", + resource_list->type); + return; + } + + /* Dump the resource descriptor */ + + acpi_rs_dump_descriptor(&resource_list->data, + acpi_gbl_dump_resource_dispatch[type]); + + /* Point to the next resource structure */ + + resource_list = + ACPI_ADD_PTR(struct acpi_resource, resource_list, + resource_list->length); + + /* Exit when END_TAG descriptor is reached */ + + } while (type != ACPI_RESOURCE_TYPE_END_TAG); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_irq_list + * + * PARAMETERS: route_table - Pointer to the routing table to dump. + * + * RETURN: None + * + * DESCRIPTION: Print IRQ routing table + * + ******************************************************************************/ + +void acpi_rs_dump_irq_list(u8 * route_table) +{ + struct acpi_pci_routing_table *prt_element; + u8 count; + + ACPI_FUNCTION_ENTRY(); + + if (!(acpi_dbg_level & ACPI_LV_RESOURCES) + || !(_COMPONENT & acpi_dbg_layer)) { + return; + } + + prt_element = ACPI_CAST_PTR(struct acpi_pci_routing_table, route_table); + + /* Dump all table elements, Exit on zero length element */ + + for (count = 0; prt_element->length; count++) { + acpi_os_printf("\n[%02X] PCI IRQ Routing Table Package\n", + count); + acpi_rs_dump_descriptor(prt_element, acpi_rs_dump_prt); + + prt_element = ACPI_ADD_PTR(struct acpi_pci_routing_table, + prt_element, prt_element->length); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_out* + * + * PARAMETERS: Title - Name of the resource field + * Value - Value of the resource field + * + * RETURN: None + * + * DESCRIPTION: Miscellaneous helper functions to consistently format the + * output of the resource dump routines + * + ******************************************************************************/ + +static void acpi_rs_out_string(char *title, char *value) +{ + acpi_os_printf("%27s : %s", title, value); + if (!*value) { + acpi_os_printf("[NULL NAMESTRING]"); + } + acpi_os_printf("\n"); +} + +static void acpi_rs_out_integer8(char *title, u8 value) +{ + acpi_os_printf("%27s : %2.2X\n", title, value); +} + +static void acpi_rs_out_integer16(char *title, u16 value) +{ + acpi_os_printf("%27s : %4.4X\n", title, value); +} + +static void acpi_rs_out_integer32(char *title, u32 value) +{ + acpi_os_printf("%27s : %8.8X\n", title, value); +} + +static void acpi_rs_out_integer64(char *title, u64 value) +{ + acpi_os_printf("%27s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value)); +} + +static void acpi_rs_out_title(char *title) +{ + acpi_os_printf("%27s : ", title); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump*List + * + * PARAMETERS: Length - Number of elements in the list + * Data - Start of the list + * + * RETURN: None + * + * DESCRIPTION: Miscellaneous functions to dump lists of raw data + * + ******************************************************************************/ + +static void acpi_rs_dump_byte_list(u16 length, u8 * data) +{ + u8 i; + + for (i = 0; i < length; i++) { + acpi_os_printf("%25s%2.2X : %2.2X\n", "Byte", i, data[i]); + } +} + +static void acpi_rs_dump_short_byte_list(u8 length, u8 * data) +{ + u8 i; + + for (i = 0; i < length; i++) { + acpi_os_printf("%X ", data[i]); + } + acpi_os_printf("\n"); +} + +static void acpi_rs_dump_dword_list(u8 length, u32 * data) +{ + u8 i; + + for (i = 0; i < length; i++) { + acpi_os_printf("%25s%2.2X : %8.8X\n", "Dword", i, data[i]); + } +} + +#endif diff --git a/drivers/acpi/acpica/rsinfo.c b/drivers/acpi/acpica/rsinfo.c new file mode 100644 index 000000000000..aac41cc21344 --- /dev/null +++ b/drivers/acpi/acpica/rsinfo.c @@ -0,0 +1,206 @@ +/******************************************************************************* + * + * Module Name: rsinfo - Dispatch and Info tables + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsinfo") + +/* + * Resource dispatch and information tables. Any new resource types (either + * Large or Small) must be reflected in each of these tables, so they are here + * in one place. + * + * The tables for Large descriptors are indexed by bits 6:0 of the AML + * descriptor type byte. The tables for Small descriptors are indexed by + * bits 6:3 of the descriptor byte. The tables for internal resource + * descriptors are indexed by the acpi_resource_type field. + */ +/* Dispatch table for resource-to-AML (Set Resource) conversion functions */ +struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[] = { + acpi_rs_set_irq, /* 0x00, ACPI_RESOURCE_TYPE_IRQ */ + acpi_rs_convert_dma, /* 0x01, ACPI_RESOURCE_TYPE_DMA */ + acpi_rs_set_start_dpf, /* 0x02, ACPI_RESOURCE_TYPE_START_DEPENDENT */ + acpi_rs_convert_end_dpf, /* 0x03, ACPI_RESOURCE_TYPE_END_DEPENDENT */ + acpi_rs_convert_io, /* 0x04, ACPI_RESOURCE_TYPE_IO */ + acpi_rs_convert_fixed_io, /* 0x05, ACPI_RESOURCE_TYPE_FIXED_IO */ + acpi_rs_set_vendor, /* 0x06, ACPI_RESOURCE_TYPE_VENDOR */ + acpi_rs_convert_end_tag, /* 0x07, ACPI_RESOURCE_TYPE_END_TAG */ + acpi_rs_convert_memory24, /* 0x08, ACPI_RESOURCE_TYPE_MEMORY24 */ + acpi_rs_convert_memory32, /* 0x09, ACPI_RESOURCE_TYPE_MEMORY32 */ + acpi_rs_convert_fixed_memory32, /* 0x0A, ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ + acpi_rs_convert_address16, /* 0x0B, ACPI_RESOURCE_TYPE_ADDRESS16 */ + acpi_rs_convert_address32, /* 0x0C, ACPI_RESOURCE_TYPE_ADDRESS32 */ + acpi_rs_convert_address64, /* 0x0D, ACPI_RESOURCE_TYPE_ADDRESS64 */ + acpi_rs_convert_ext_address64, /* 0x0E, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ + acpi_rs_convert_ext_irq, /* 0x0F, ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ + acpi_rs_convert_generic_reg /* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ +}; + +/* Dispatch tables for AML-to-resource (Get Resource) conversion functions */ + +struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[] = { + /* Small descriptors */ + + NULL, /* 0x00, Reserved */ + NULL, /* 0x01, Reserved */ + NULL, /* 0x02, Reserved */ + NULL, /* 0x03, Reserved */ + acpi_rs_get_irq, /* 0x04, ACPI_RESOURCE_NAME_IRQ */ + acpi_rs_convert_dma, /* 0x05, ACPI_RESOURCE_NAME_DMA */ + acpi_rs_get_start_dpf, /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */ + acpi_rs_convert_end_dpf, /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */ + acpi_rs_convert_io, /* 0x08, ACPI_RESOURCE_NAME_IO */ + acpi_rs_convert_fixed_io, /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO */ + NULL, /* 0x0A, Reserved */ + NULL, /* 0x0B, Reserved */ + NULL, /* 0x0C, Reserved */ + NULL, /* 0x0D, Reserved */ + acpi_rs_get_vendor_small, /* 0x0E, ACPI_RESOURCE_NAME_VENDOR_SMALL */ + acpi_rs_convert_end_tag, /* 0x0F, ACPI_RESOURCE_NAME_END_TAG */ + + /* Large descriptors */ + + NULL, /* 0x00, Reserved */ + acpi_rs_convert_memory24, /* 0x01, ACPI_RESOURCE_NAME_MEMORY24 */ + acpi_rs_convert_generic_reg, /* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */ + NULL, /* 0x03, Reserved */ + acpi_rs_get_vendor_large, /* 0x04, ACPI_RESOURCE_NAME_VENDOR_LARGE */ + acpi_rs_convert_memory32, /* 0x05, ACPI_RESOURCE_NAME_MEMORY32 */ + acpi_rs_convert_fixed_memory32, /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY32 */ + acpi_rs_convert_address32, /* 0x07, ACPI_RESOURCE_NAME_ADDRESS32 */ + acpi_rs_convert_address16, /* 0x08, ACPI_RESOURCE_NAME_ADDRESS16 */ + acpi_rs_convert_ext_irq, /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_IRQ */ + acpi_rs_convert_address64, /* 0x0A, ACPI_RESOURCE_NAME_ADDRESS64 */ + acpi_rs_convert_ext_address64 /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */ +}; + +#ifdef ACPI_FUTURE_USAGE +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +/* Dispatch table for resource dump functions */ + +struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = { + acpi_rs_dump_irq, /* ACPI_RESOURCE_TYPE_IRQ */ + acpi_rs_dump_dma, /* ACPI_RESOURCE_TYPE_DMA */ + acpi_rs_dump_start_dpf, /* ACPI_RESOURCE_TYPE_START_DEPENDENT */ + acpi_rs_dump_end_dpf, /* ACPI_RESOURCE_TYPE_END_DEPENDENT */ + acpi_rs_dump_io, /* ACPI_RESOURCE_TYPE_IO */ + acpi_rs_dump_fixed_io, /* ACPI_RESOURCE_TYPE_FIXED_IO */ + acpi_rs_dump_vendor, /* ACPI_RESOURCE_TYPE_VENDOR */ + acpi_rs_dump_end_tag, /* ACPI_RESOURCE_TYPE_END_TAG */ + acpi_rs_dump_memory24, /* ACPI_RESOURCE_TYPE_MEMORY24 */ + acpi_rs_dump_memory32, /* ACPI_RESOURCE_TYPE_MEMORY32 */ + acpi_rs_dump_fixed_memory32, /* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ + acpi_rs_dump_address16, /* ACPI_RESOURCE_TYPE_ADDRESS16 */ + acpi_rs_dump_address32, /* ACPI_RESOURCE_TYPE_ADDRESS32 */ + acpi_rs_dump_address64, /* ACPI_RESOURCE_TYPE_ADDRESS64 */ + acpi_rs_dump_ext_address64, /* ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ + acpi_rs_dump_ext_irq, /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ + acpi_rs_dump_generic_reg, /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ +}; +#endif + +#endif /* ACPI_FUTURE_USAGE */ +/* + * Base sizes for external AML resource descriptors, indexed by internal type. + * Includes size of the descriptor header (1 byte for small descriptors, + * 3 bytes for large descriptors) + */ +const u8 acpi_gbl_aml_resource_sizes[] = { + sizeof(struct aml_resource_irq), /* ACPI_RESOURCE_TYPE_IRQ (optional Byte 3 always created) */ + sizeof(struct aml_resource_dma), /* ACPI_RESOURCE_TYPE_DMA */ + sizeof(struct aml_resource_start_dependent), /* ACPI_RESOURCE_TYPE_START_DEPENDENT (optional Byte 1 always created) */ + sizeof(struct aml_resource_end_dependent), /* ACPI_RESOURCE_TYPE_END_DEPENDENT */ + sizeof(struct aml_resource_io), /* ACPI_RESOURCE_TYPE_IO */ + sizeof(struct aml_resource_fixed_io), /* ACPI_RESOURCE_TYPE_FIXED_IO */ + sizeof(struct aml_resource_vendor_small), /* ACPI_RESOURCE_TYPE_VENDOR */ + sizeof(struct aml_resource_end_tag), /* ACPI_RESOURCE_TYPE_END_TAG */ + sizeof(struct aml_resource_memory24), /* ACPI_RESOURCE_TYPE_MEMORY24 */ + sizeof(struct aml_resource_memory32), /* ACPI_RESOURCE_TYPE_MEMORY32 */ + sizeof(struct aml_resource_fixed_memory32), /* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ + sizeof(struct aml_resource_address16), /* ACPI_RESOURCE_TYPE_ADDRESS16 */ + sizeof(struct aml_resource_address32), /* ACPI_RESOURCE_TYPE_ADDRESS32 */ + sizeof(struct aml_resource_address64), /* ACPI_RESOURCE_TYPE_ADDRESS64 */ + sizeof(struct aml_resource_extended_address64), /*ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ + sizeof(struct aml_resource_extended_irq), /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ + sizeof(struct aml_resource_generic_register) /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ +}; + +const u8 acpi_gbl_resource_struct_sizes[] = { + /* Small descriptors */ + + 0, + 0, + 0, + 0, + ACPI_RS_SIZE(struct acpi_resource_irq), + ACPI_RS_SIZE(struct acpi_resource_dma), + ACPI_RS_SIZE(struct acpi_resource_start_dependent), + ACPI_RS_SIZE_MIN, + ACPI_RS_SIZE(struct acpi_resource_io), + ACPI_RS_SIZE(struct acpi_resource_fixed_io), + 0, + 0, + 0, + 0, + ACPI_RS_SIZE(struct acpi_resource_vendor), + ACPI_RS_SIZE_MIN, + + /* Large descriptors */ + + 0, + ACPI_RS_SIZE(struct acpi_resource_memory24), + ACPI_RS_SIZE(struct acpi_resource_generic_register), + 0, + ACPI_RS_SIZE(struct acpi_resource_vendor), + ACPI_RS_SIZE(struct acpi_resource_memory32), + ACPI_RS_SIZE(struct acpi_resource_fixed_memory32), + ACPI_RS_SIZE(struct acpi_resource_address32), + ACPI_RS_SIZE(struct acpi_resource_address16), + ACPI_RS_SIZE(struct acpi_resource_extended_irq), + ACPI_RS_SIZE(struct acpi_resource_address64), + ACPI_RS_SIZE(struct acpi_resource_extended_address64) +}; diff --git a/drivers/acpi/acpica/rsio.c b/drivers/acpi/acpica/rsio.c new file mode 100644 index 000000000000..d31129aca400 --- /dev/null +++ b/drivers/acpi/acpica/rsio.c @@ -0,0 +1,290 @@ +/******************************************************************************* + * + * Module Name: rsio - IO and DMA resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsio") + +/******************************************************************************* + * + * acpi_rs_convert_io + * + ******************************************************************************/ +struct acpi_rsconvert_info acpi_rs_convert_io[5] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IO, + ACPI_RS_SIZE(struct acpi_resource_io), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IO, + sizeof(struct aml_resource_io), + 0}, + + /* Decode flag */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.io.io_decode), + AML_OFFSET(io.flags), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Address Alignment + * Length + * Minimum Base Address + * Maximum Base Address + */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.io.alignment), + AML_OFFSET(io.alignment), + 2}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.io.minimum), + AML_OFFSET(io.minimum), + 2} +}; + +/******************************************************************************* + * + * acpi_rs_convert_fixed_io + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_fixed_io[4] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_IO, + ACPI_RS_SIZE(struct acpi_resource_fixed_io), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_io)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_IO, + sizeof(struct aml_resource_fixed_io), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Base Address + * Length + */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.fixed_io.address_length), + AML_OFFSET(fixed_io.address_length), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.fixed_io.address), + AML_OFFSET(fixed_io.address), + 1} +}; + +/******************************************************************************* + * + * acpi_rs_convert_generic_reg + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_generic_reg[4] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GENERIC_REGISTER, + ACPI_RS_SIZE(struct acpi_resource_generic_register), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_generic_reg)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_GENERIC_REGISTER, + sizeof(struct aml_resource_generic_register), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Address Space ID + * Register Bit Width + * Register Bit Offset + * Access Size + */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.generic_reg.space_id), + AML_OFFSET(generic_reg.address_space_id), + 4}, + + /* Get the Register Address */ + + {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.generic_reg.address), + AML_OFFSET(generic_reg.address), + 1} +}; + +/******************************************************************************* + * + * acpi_rs_convert_end_dpf + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_end_dpf[2] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_DEPENDENT, + ACPI_RS_SIZE_MIN, + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_end_dpf)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_DEPENDENT, + sizeof(struct aml_resource_end_dependent), + 0} +}; + +/******************************************************************************* + * + * acpi_rs_convert_end_tag + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_end_tag[2] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_TAG, + ACPI_RS_SIZE_MIN, + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_end_tag)}, + + /* + * Note: The checksum field is set to zero, meaning that the resource + * data is treated as if the checksum operation succeeded. + * (ACPI Spec 1.0b Section 6.4.2.8) + */ + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_TAG, + sizeof(struct aml_resource_end_tag), + 0} +}; + +/******************************************************************************* + * + * acpi_rs_get_start_dpf + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_get_start_dpf[6] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_START_DEPENDENT, + ACPI_RS_SIZE(struct acpi_resource_start_dependent), + ACPI_RSC_TABLE_SIZE(acpi_rs_get_start_dpf)}, + + /* Defaults for Compatibility and Performance priorities */ + + {ACPI_RSC_SET8, ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), + ACPI_ACCEPTABLE_CONFIGURATION, + 2}, + + /* Get the descriptor length (0 or 1 for Start Dpf descriptor) */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.start_dpf.descriptor_length), + AML_OFFSET(start_dpf.descriptor_type), + 0}, + + /* All done if there is no flag byte present in the descriptor */ + + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 1}, + + /* Flag byte is present, get the flags */ + + {ACPI_RSC_2BITFLAG, + ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), + AML_OFFSET(start_dpf.flags), + 0}, + + {ACPI_RSC_2BITFLAG, + ACPI_RS_OFFSET(data.start_dpf.performance_robustness), + AML_OFFSET(start_dpf.flags), + 2} +}; + +/******************************************************************************* + * + * acpi_rs_set_start_dpf + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_set_start_dpf[10] = { + /* Start with a default descriptor of length 1 */ + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_START_DEPENDENT, + sizeof(struct aml_resource_start_dependent), + ACPI_RSC_TABLE_SIZE(acpi_rs_set_start_dpf)}, + + /* Set the default flag values */ + + {ACPI_RSC_2BITFLAG, + ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), + AML_OFFSET(start_dpf.flags), + 0}, + + {ACPI_RSC_2BITFLAG, + ACPI_RS_OFFSET(data.start_dpf.performance_robustness), + AML_OFFSET(start_dpf.flags), + 2}, + /* + * All done if the output descriptor length is required to be 1 + * (i.e., optimization to 0 bytes cannot be attempted) + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.start_dpf.descriptor_length), + 1}, + + /* Set length to 0 bytes (no flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, + sizeof(struct aml_resource_start_dependent_noprio)}, + + /* + * All done if the output descriptor length is required to be 0. + * + * TBD: Perhaps we should check for error if input flags are not + * compatible with a 0-byte descriptor. + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.start_dpf.descriptor_length), + 0}, + + /* Reset length to 1 byte (descriptor with flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_start_dependent)}, + + /* + * All done if flags byte is necessary -- if either priority value + * is not ACPI_ACCEPTABLE_CONFIGURATION + */ + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), + ACPI_ACCEPTABLE_CONFIGURATION}, + + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.start_dpf.performance_robustness), + ACPI_ACCEPTABLE_CONFIGURATION}, + + /* Flag byte is not necessary */ + + {ACPI_RSC_LENGTH, 0, 0, + sizeof(struct aml_resource_start_dependent_noprio)} +}; diff --git a/drivers/acpi/acpica/rsirq.c b/drivers/acpi/acpica/rsirq.c new file mode 100644 index 000000000000..9a5a08d67313 --- /dev/null +++ b/drivers/acpi/acpica/rsirq.c @@ -0,0 +1,266 @@ +/******************************************************************************* + * + * Module Name: rsirq - IRQ resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsirq") + +/******************************************************************************* + * + * acpi_rs_get_irq + * + ******************************************************************************/ +struct acpi_rsconvert_info acpi_rs_get_irq[8] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, + ACPI_RS_SIZE(struct acpi_resource_irq), + ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)}, + + /* Get the IRQ mask (bytes 1:2) */ + + {ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]), + AML_OFFSET(irq.irq_mask), + ACPI_RS_OFFSET(data.irq.interrupt_count)}, + + /* Set default flags (others are zero) */ + + {ACPI_RSC_SET8, ACPI_RS_OFFSET(data.irq.triggering), + ACPI_EDGE_SENSITIVE, + 1}, + + /* Get the descriptor length (2 or 3 for IRQ descriptor) */ + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.irq.descriptor_length), + AML_OFFSET(irq.descriptor_type), + 0}, + + /* All done if no flag byte present in descriptor */ + + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, + + /* Get flags: Triggering[0], Polarity[3], Sharing[4] */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), + AML_OFFSET(irq.flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity), + AML_OFFSET(irq.flags), + 3}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), + AML_OFFSET(irq.flags), + 4} +}; + +/******************************************************************************* + * + * acpi_rs_set_irq + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_set_irq[13] = { + /* Start with a default descriptor of length 3 */ + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, + sizeof(struct aml_resource_irq), + ACPI_RSC_TABLE_SIZE(acpi_rs_set_irq)}, + + /* Convert interrupt list to 16-bit IRQ bitmask */ + + {ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]), + AML_OFFSET(irq.irq_mask), + ACPI_RS_OFFSET(data.irq.interrupt_count)}, + + /* Set the flags byte */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), + AML_OFFSET(irq.flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity), + AML_OFFSET(irq.flags), + 3}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), + AML_OFFSET(irq.flags), + 4}, + + /* + * All done if the output descriptor length is required to be 3 + * (i.e., optimization to 2 bytes cannot be attempted) + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.descriptor_length), + 3}, + + /* Set length to 2 bytes (no flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)}, + + /* + * All done if the output descriptor length is required to be 2. + * + * TBD: Perhaps we should check for error if input flags are not + * compatible with a 2-byte descriptor. + */ + {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.descriptor_length), + 2}, + + /* Reset length to 3 bytes (descriptor with flags byte) */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq)}, + + /* + * Check if the flags byte is necessary. Not needed if the flags are: + * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE + */ + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.triggering), + ACPI_EDGE_SENSITIVE}, + + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.polarity), + ACPI_ACTIVE_HIGH}, + + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.sharable), + ACPI_EXCLUSIVE}, + + /* We can optimize to a 2-byte irq_no_flags() descriptor */ + + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)} +}; + +/******************************************************************************* + * + * acpi_rs_convert_ext_irq + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ, + ACPI_RS_SIZE(struct acpi_resource_extended_irq), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_irq)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_IRQ, + sizeof(struct aml_resource_extended_irq), + 0}, + + /* Flag bits */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.producer_consumer), + AML_OFFSET(extended_irq.flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.triggering), + AML_OFFSET(extended_irq.flags), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.polarity), + AML_OFFSET(extended_irq.flags), + 2}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.sharable), + AML_OFFSET(extended_irq.flags), + 3}, + + /* IRQ Table length (Byte4) */ + + {ACPI_RSC_COUNT, ACPI_RS_OFFSET(data.extended_irq.interrupt_count), + AML_OFFSET(extended_irq.interrupt_count), + sizeof(u32)} + , + + /* Copy every IRQ in the table, each is 32 bits */ + + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.extended_irq.interrupts[0]), + AML_OFFSET(extended_irq.interrupts[0]), + 0} + , + + /* Optional resource_source (Index and String) */ + + {ACPI_RSC_SOURCEX, ACPI_RS_OFFSET(data.extended_irq.resource_source), + ACPI_RS_OFFSET(data.extended_irq.interrupts[0]), + sizeof(struct aml_resource_extended_irq)} +}; + +/******************************************************************************* + * + * acpi_rs_convert_dma + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_dma[6] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_DMA, + ACPI_RS_SIZE(struct acpi_resource_dma), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_dma)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_DMA, + sizeof(struct aml_resource_dma), + 0}, + + /* Flags: transfer preference, bus mastering, channel speed */ + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.transfer), + AML_OFFSET(dma.flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.dma.bus_master), + AML_OFFSET(dma.flags), + 2}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.type), + AML_OFFSET(dma.flags), + 5}, + + /* DMA channel mask bits */ + + {ACPI_RSC_BITMASK, ACPI_RS_OFFSET(data.dma.channels[0]), + AML_OFFSET(dma.dma_channel_mask), + ACPI_RS_OFFSET(data.dma.channel_count)} +}; diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c new file mode 100644 index 000000000000..483389871a50 --- /dev/null +++ b/drivers/acpi/acpica/rslist.c @@ -0,0 +1,203 @@ +/******************************************************************************* + * + * Module Name: rslist - Linked list utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rslist") + +/******************************************************************************* + * + * FUNCTION: acpi_rs_convert_aml_to_resources + * + * PARAMETERS: acpi_walk_aml_callback + * resource_ptr - Pointer to the buffer that will + * contain the output structures + * + * RETURN: Status + * + * DESCRIPTION: Convert an AML resource to an internal representation of the + * resource that is aligned and easier to access. + * + ******************************************************************************/ +acpi_status +acpi_rs_convert_aml_to_resources(u8 * aml, + u32 length, + u32 offset, u8 resource_index, void **context) +{ + struct acpi_resource **resource_ptr = + ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context); + struct acpi_resource *resource; + acpi_status status; + + ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources); + + /* + * Check that the input buffer and all subsequent pointers into it + * are aligned on a native word boundary. Most important on IA64 + */ + resource = *resource_ptr; + if (ACPI_IS_MISALIGNED(resource)) { + ACPI_WARNING((AE_INFO, + "Misaligned resource pointer %p", resource)); + } + + /* Convert the AML byte stream resource to a local resource struct */ + + status = + acpi_rs_convert_aml_to_resource(resource, + ACPI_CAST_PTR(union aml_resource, + aml), + acpi_gbl_get_resource_dispatch + [resource_index]); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not convert AML resource (Type %X)", + *aml)); + return_ACPI_STATUS(status); + } + + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, + "Type %.2X, AmlLength %.2X InternalLength %.2X\n", + acpi_ut_get_resource_type(aml), length, + resource->length)); + + /* Point to the next structure in the output buffer */ + + *resource_ptr = ACPI_ADD_PTR(void, resource, resource->length); + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_convert_resources_to_aml + * + * PARAMETERS: Resource - Pointer to the resource linked list + * aml_size_needed - Calculated size of the byte stream + * needed from calling acpi_rs_get_aml_length() + * The size of the output_buffer is + * guaranteed to be >= aml_size_needed + * output_buffer - Pointer to the buffer that will + * contain the byte stream + * + * RETURN: Status + * + * DESCRIPTION: Takes the resource linked list and parses it, creating a + * byte stream of resources in the caller's output buffer + * + ******************************************************************************/ + +acpi_status +acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, + acpi_size aml_size_needed, u8 * output_buffer) +{ + u8 *aml = output_buffer; + u8 *end_aml = output_buffer + aml_size_needed; + acpi_status status; + + ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml); + + /* Walk the resource descriptor list, convert each descriptor */ + + while (aml < end_aml) { + + /* Validate the (internal) Resource Type */ + + if (resource->type > ACPI_RESOURCE_TYPE_MAX) { + ACPI_ERROR((AE_INFO, + "Invalid descriptor type (%X) in resource list", + resource->type)); + return_ACPI_STATUS(AE_BAD_DATA); + } + + /* Perform the conversion */ + + status = acpi_rs_convert_resource_to_aml(resource, ACPI_CAST_PTR(union + aml_resource, + aml), + acpi_gbl_set_resource_dispatch + [resource->type]); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not convert resource (type %X) to AML", + resource->type)); + return_ACPI_STATUS(status); + } + + /* Perform final sanity check on the new AML resource descriptor */ + + status = + acpi_ut_validate_resource(ACPI_CAST_PTR + (union aml_resource, aml), NULL); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Check for end-of-list, normal exit */ + + if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { + + /* An End Tag indicates the end of the input Resource Template */ + + return_ACPI_STATUS(AE_OK); + } + + /* + * Extract the total length of the new descriptor and set the + * Aml to point to the next (output) resource descriptor + */ + aml += acpi_ut_get_descriptor_length(aml); + + /* Point to the next input resource descriptor */ + + resource = + ACPI_ADD_PTR(struct acpi_resource, resource, + resource->length); + } + + /* Completed buffer, but did not find an end_tag resource descriptor */ + + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); +} diff --git a/drivers/acpi/acpica/rsmemory.c b/drivers/acpi/acpica/rsmemory.c new file mode 100644 index 000000000000..5fd3746cca54 --- /dev/null +++ b/drivers/acpi/acpica/rsmemory.c @@ -0,0 +1,236 @@ +/******************************************************************************* + * + * Module Name: rsmem24 - Memory resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsmemory") + +/******************************************************************************* + * + * acpi_rs_convert_memory24 + * + ******************************************************************************/ +struct acpi_rsconvert_info acpi_rs_convert_memory24[4] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY24, + ACPI_RS_SIZE(struct acpi_resource_memory24), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_memory24)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY24, + sizeof(struct aml_resource_memory24), + 0}, + + /* Read/Write bit */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.memory24.write_protect), + AML_OFFSET(memory24.flags), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Minimum Base Address + * Maximum Base Address + * Address Base Alignment + * Range Length + */ + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.memory24.minimum), + AML_OFFSET(memory24.minimum), + 4} +}; + +/******************************************************************************* + * + * acpi_rs_convert_memory32 + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_memory32[4] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY32, + ACPI_RS_SIZE(struct acpi_resource_memory32), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_memory32)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY32, + sizeof(struct aml_resource_memory32), + 0}, + + /* Read/Write bit */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.memory32.write_protect), + AML_OFFSET(memory32.flags), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Minimum Base Address + * Maximum Base Address + * Address Base Alignment + * Range Length + */ + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.memory32.minimum), + AML_OFFSET(memory32.minimum), + 4} +}; + +/******************************************************************************* + * + * acpi_rs_convert_fixed_memory32 + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_fixed_memory32[4] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_MEMORY32, + ACPI_RS_SIZE(struct acpi_resource_fixed_memory32), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_memory32)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_MEMORY32, + sizeof(struct aml_resource_fixed_memory32), + 0}, + + /* Read/Write bit */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.fixed_memory32.write_protect), + AML_OFFSET(fixed_memory32.flags), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Base Address + * Range Length + */ + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.fixed_memory32.address), + AML_OFFSET(fixed_memory32.address), + 2} +}; + +/******************************************************************************* + * + * acpi_rs_get_vendor_small + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_get_vendor_small[3] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR, + ACPI_RS_SIZE(struct acpi_resource_vendor), + ACPI_RSC_TABLE_SIZE(acpi_rs_get_vendor_small)}, + + /* Length of the vendor data (byte count) */ + + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), + 0, + sizeof(u8)} + , + + /* Vendor data */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), + sizeof(struct aml_resource_small_header), + 0} +}; + +/******************************************************************************* + * + * acpi_rs_get_vendor_large + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_get_vendor_large[3] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR, + ACPI_RS_SIZE(struct acpi_resource_vendor), + ACPI_RSC_TABLE_SIZE(acpi_rs_get_vendor_large)}, + + /* Length of the vendor data (byte count) */ + + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), + 0, + sizeof(u8)} + , + + /* Vendor data */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), + sizeof(struct aml_resource_large_header), + 0} +}; + +/******************************************************************************* + * + * acpi_rs_set_vendor + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_set_vendor[7] = { + /* Default is a small vendor descriptor */ + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_SMALL, + sizeof(struct aml_resource_small_header), + ACPI_RSC_TABLE_SIZE(acpi_rs_set_vendor)}, + + /* Get the length and copy the data */ + + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), + 0, + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), + sizeof(struct aml_resource_small_header), + 0}, + + /* + * All done if the Vendor byte length is 7 or less, meaning that it will + * fit within a small descriptor + */ + {ACPI_RSC_EXIT_LE, 0, 0, 7}, + + /* Must create a large vendor descriptor */ + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_LARGE, + sizeof(struct aml_resource_large_header), + 0}, + + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), + 0, + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), + sizeof(struct aml_resource_large_header), + 0} +}; diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c new file mode 100644 index 000000000000..2cd6e8cfaba1 --- /dev/null +++ b/drivers/acpi/acpica/rsmisc.c @@ -0,0 +1,561 @@ +/******************************************************************************* + * + * Module Name: rsmisc - Miscellaneous resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsmisc") +#define INIT_RESOURCE_TYPE(i) i->resource_offset +#define INIT_RESOURCE_LENGTH(i) i->aml_offset +#define INIT_TABLE_LENGTH(i) i->value +#define COMPARE_OPCODE(i) i->resource_offset +#define COMPARE_TARGET(i) i->aml_offset +#define COMPARE_VALUE(i) i->value +/******************************************************************************* + * + * FUNCTION: acpi_rs_convert_aml_to_resource + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Aml - Where the AML descriptor is returned + * Info - Pointer to appropriate conversion table + * + * RETURN: Status + * + * DESCRIPTION: Convert an external AML resource descriptor to the corresponding + * internal resource descriptor + * + ******************************************************************************/ +acpi_status +acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, + union aml_resource *aml, + struct acpi_rsconvert_info *info) +{ + acpi_rs_length aml_resource_length; + void *source; + void *destination; + char *target; + u8 count; + u8 flags_mode = FALSE; + u16 item_count = 0; + u16 temp16 = 0; + + ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource); + + if (((acpi_size) resource) & 0x3) { + + /* Each internal resource struct is expected to be 32-bit aligned */ + + ACPI_WARNING((AE_INFO, + "Misaligned resource pointer (get): %p Type %2.2X Len %X", + resource, resource->type, resource->length)); + } + + /* Extract the resource Length field (does not include header length) */ + + aml_resource_length = acpi_ut_get_resource_length(aml); + + /* + * First table entry must be ACPI_RSC_INITxxx and must contain the + * table length (# of table entries) + */ + count = INIT_TABLE_LENGTH(info); + + while (count) { + /* + * Source is the external AML byte stream buffer, + * destination is the internal resource descriptor + */ + source = ACPI_ADD_PTR(void, aml, info->aml_offset); + destination = + ACPI_ADD_PTR(void, resource, info->resource_offset); + + switch (info->opcode) { + case ACPI_RSC_INITGET: + /* + * Get the resource type and the initial (minimum) length + */ + ACPI_MEMSET(resource, 0, INIT_RESOURCE_LENGTH(info)); + resource->type = INIT_RESOURCE_TYPE(info); + resource->length = INIT_RESOURCE_LENGTH(info); + break; + + case ACPI_RSC_INITSET: + break; + + case ACPI_RSC_FLAGINIT: + + flags_mode = TRUE; + break; + + case ACPI_RSC_1BITFLAG: + /* + * Mask and shift the flag bit + */ + ACPI_SET8(destination) = (u8) + ((ACPI_GET8(source) >> info->value) & 0x01); + break; + + case ACPI_RSC_2BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET8(destination) = (u8) + ((ACPI_GET8(source) >> info->value) & 0x03); + break; + + case ACPI_RSC_COUNT: + + item_count = ACPI_GET8(source); + ACPI_SET8(destination) = (u8) item_count; + + resource->length = resource->length + + (info->value * (item_count - 1)); + break; + + case ACPI_RSC_COUNT16: + + item_count = aml_resource_length; + ACPI_SET16(destination) = item_count; + + resource->length = resource->length + + (info->value * (item_count - 1)); + break; + + case ACPI_RSC_LENGTH: + + resource->length = resource->length + info->value; + break; + + case ACPI_RSC_MOVE8: + case ACPI_RSC_MOVE16: + case ACPI_RSC_MOVE32: + case ACPI_RSC_MOVE64: + /* + * Raw data move. Use the Info value field unless item_count has + * been previously initialized via a COUNT opcode + */ + if (info->value) { + item_count = info->value; + } + acpi_rs_move_data(destination, source, item_count, + info->opcode); + break; + + case ACPI_RSC_SET8: + + ACPI_MEMSET(destination, info->aml_offset, info->value); + break; + + case ACPI_RSC_DATA8: + + target = ACPI_ADD_PTR(char, resource, info->value); + ACPI_MEMCPY(destination, source, ACPI_GET16(target)); + break; + + case ACPI_RSC_ADDRESS: + /* + * Common handler for address descriptor flags + */ + if (!acpi_rs_get_address_common(resource, aml)) { + return_ACPI_STATUS + (AE_AML_INVALID_RESOURCE_TYPE); + } + break; + + case ACPI_RSC_SOURCE: + /* + * Optional resource_source (Index and String) + */ + resource->length += + acpi_rs_get_resource_source(aml_resource_length, + info->value, + destination, aml, NULL); + break; + + case ACPI_RSC_SOURCEX: + /* + * Optional resource_source (Index and String). This is the more + * complicated case used by the Interrupt() macro + */ + target = + ACPI_ADD_PTR(char, resource, + info->aml_offset + (item_count * 4)); + + resource->length += + acpi_rs_get_resource_source(aml_resource_length, + (acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target); + break; + + case ACPI_RSC_BITMASK: + /* + * 8-bit encoded bitmask (DMA macro) + */ + item_count = + acpi_rs_decode_bitmask(ACPI_GET8(source), + destination); + if (item_count) { + resource->length += (item_count - 1); + } + + target = ACPI_ADD_PTR(char, resource, info->value); + ACPI_SET8(target) = (u8) item_count; + break; + + case ACPI_RSC_BITMASK16: + /* + * 16-bit encoded bitmask (IRQ macro) + */ + ACPI_MOVE_16_TO_16(&temp16, source); + + item_count = + acpi_rs_decode_bitmask(temp16, destination); + if (item_count) { + resource->length += (item_count - 1); + } + + target = ACPI_ADD_PTR(char, resource, info->value); + ACPI_SET8(target) = (u8) item_count; + break; + + case ACPI_RSC_EXIT_NE: + /* + * Control - Exit conversion if not equal + */ + switch (info->resource_offset) { + case ACPI_RSC_COMPARE_AML_LENGTH: + if (aml_resource_length != info->value) { + goto exit; + } + break; + + case ACPI_RSC_COMPARE_VALUE: + if (ACPI_GET8(source) != info->value) { + goto exit; + } + break; + + default: + + ACPI_ERROR((AE_INFO, + "Invalid conversion sub-opcode")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + count--; + info++; + } + + exit: + if (!flags_mode) { + + /* Round the resource struct length up to the next boundary (32 or 64) */ + + resource->length = + (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length); + } + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_convert_resource_to_aml + * + * PARAMETERS: Resource - Pointer to the resource descriptor + * Aml - Where the AML descriptor is returned + * Info - Pointer to appropriate conversion table + * + * RETURN: Status + * + * DESCRIPTION: Convert an internal resource descriptor to the corresponding + * external AML resource descriptor. + * + ******************************************************************************/ + +acpi_status +acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, + union aml_resource *aml, + struct acpi_rsconvert_info *info) +{ + void *source = NULL; + void *destination; + acpi_rsdesc_size aml_length = 0; + u8 count; + u16 temp16 = 0; + u16 item_count = 0; + + ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml); + + /* + * First table entry must be ACPI_RSC_INITxxx and must contain the + * table length (# of table entries) + */ + count = INIT_TABLE_LENGTH(info); + + while (count) { + /* + * Source is the internal resource descriptor, + * destination is the external AML byte stream buffer + */ + source = ACPI_ADD_PTR(void, resource, info->resource_offset); + destination = ACPI_ADD_PTR(void, aml, info->aml_offset); + + switch (info->opcode) { + case ACPI_RSC_INITSET: + + ACPI_MEMSET(aml, 0, INIT_RESOURCE_LENGTH(info)); + aml_length = INIT_RESOURCE_LENGTH(info); + acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info), + aml_length, aml); + break; + + case ACPI_RSC_INITGET: + break; + + case ACPI_RSC_FLAGINIT: + /* + * Clear the flag byte + */ + ACPI_SET8(destination) = 0; + break; + + case ACPI_RSC_1BITFLAG: + /* + * Mask and shift the flag bit + */ + ACPI_SET8(destination) |= (u8) + ((ACPI_GET8(source) & 0x01) << info->value); + break; + + case ACPI_RSC_2BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET8(destination) |= (u8) + ((ACPI_GET8(source) & 0x03) << info->value); + break; + + case ACPI_RSC_COUNT: + + item_count = ACPI_GET8(source); + ACPI_SET8(destination) = (u8) item_count; + + aml_length = + (u16) (aml_length + + (info->value * (item_count - 1))); + break; + + case ACPI_RSC_COUNT16: + + item_count = ACPI_GET16(source); + aml_length = (u16) (aml_length + item_count); + acpi_rs_set_resource_length(aml_length, aml); + break; + + case ACPI_RSC_LENGTH: + + acpi_rs_set_resource_length(info->value, aml); + break; + + case ACPI_RSC_MOVE8: + case ACPI_RSC_MOVE16: + case ACPI_RSC_MOVE32: + case ACPI_RSC_MOVE64: + + if (info->value) { + item_count = info->value; + } + acpi_rs_move_data(destination, source, item_count, + info->opcode); + break; + + case ACPI_RSC_ADDRESS: + + /* Set the Resource Type, General Flags, and Type-Specific Flags */ + + acpi_rs_set_address_common(aml, resource); + break; + + case ACPI_RSC_SOURCEX: + /* + * Optional resource_source (Index and String) + */ + aml_length = + acpi_rs_set_resource_source(aml, (acpi_rs_length) + aml_length, source); + acpi_rs_set_resource_length(aml_length, aml); + break; + + case ACPI_RSC_SOURCE: + /* + * Optional resource_source (Index and String). This is the more + * complicated case used by the Interrupt() macro + */ + aml_length = + acpi_rs_set_resource_source(aml, info->value, + source); + acpi_rs_set_resource_length(aml_length, aml); + break; + + case ACPI_RSC_BITMASK: + /* + * 8-bit encoded bitmask (DMA macro) + */ + ACPI_SET8(destination) = (u8) + acpi_rs_encode_bitmask(source, + *ACPI_ADD_PTR(u8, resource, + info->value)); + break; + + case ACPI_RSC_BITMASK16: + /* + * 16-bit encoded bitmask (IRQ macro) + */ + temp16 = acpi_rs_encode_bitmask(source, + *ACPI_ADD_PTR(u8, + resource, + info-> + value)); + ACPI_MOVE_16_TO_16(destination, &temp16); + break; + + case ACPI_RSC_EXIT_LE: + /* + * Control - Exit conversion if less than or equal + */ + if (item_count <= info->value) { + goto exit; + } + break; + + case ACPI_RSC_EXIT_NE: + /* + * Control - Exit conversion if not equal + */ + switch (COMPARE_OPCODE(info)) { + case ACPI_RSC_COMPARE_VALUE: + + if (*ACPI_ADD_PTR(u8, resource, + COMPARE_TARGET(info)) != + COMPARE_VALUE(info)) { + goto exit; + } + break; + + default: + + ACPI_ERROR((AE_INFO, + "Invalid conversion sub-opcode")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + break; + + case ACPI_RSC_EXIT_EQ: + /* + * Control - Exit conversion if equal + */ + if (*ACPI_ADD_PTR(u8, resource, + COMPARE_TARGET(info)) == + COMPARE_VALUE(info)) { + goto exit; + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + count--; + info++; + } + + exit: + return_ACPI_STATUS(AE_OK); +} + +#if 0 +/* Previous resource validations */ + +if (aml->ext_address64.revision_iD != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) { + return_ACPI_STATUS(AE_SUPPORT); +} + +if (resource->data.start_dpf.performance_robustness >= 3) { + return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE); +} + +if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) { + /* + * Only [active_high, edge_sensitive] or [active_low, level_sensitive] + * polarity/trigger interrupts are allowed (ACPI spec, section + * "IRQ Format"), so 0x00 and 0x09 are illegal. + */ + ACPI_ERROR((AE_INFO, + "Invalid interrupt polarity/trigger in resource list, %X", + aml->irq.flags)); + return_ACPI_STATUS(AE_BAD_DATA); +} + +resource->data.extended_irq.interrupt_count = temp8; +if (temp8 < 1) { + + /* Must have at least one IRQ */ + + return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); +} + +if (resource->data.dma.transfer == 0x03) { + ACPI_ERROR((AE_INFO, "Invalid DMA.Transfer preference (3)")); + return_ACPI_STATUS(AE_BAD_DATA); +} +#endif diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c new file mode 100644 index 000000000000..7450105f8548 --- /dev/null +++ b/drivers/acpi/acpica/rsutils.c @@ -0,0 +1,727 @@ +/******************************************************************************* + * + * Module Name: rsutils - Utilities for the resource manager + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsutils") + +/******************************************************************************* + * + * FUNCTION: acpi_rs_decode_bitmask + * + * PARAMETERS: Mask - Bitmask to decode + * List - Where the converted list is returned + * + * RETURN: Count of bits set (length of list) + * + * DESCRIPTION: Convert a bit mask into a list of values + * + ******************************************************************************/ +u8 acpi_rs_decode_bitmask(u16 mask, u8 * list) +{ + u8 i; + u8 bit_count; + + ACPI_FUNCTION_ENTRY(); + + /* Decode the mask bits */ + + for (i = 0, bit_count = 0; mask; i++) { + if (mask & 0x0001) { + list[bit_count] = i; + bit_count++; + } + + mask >>= 1; + } + + return (bit_count); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_encode_bitmask + * + * PARAMETERS: List - List of values to encode + * Count - Length of list + * + * RETURN: Encoded bitmask + * + * DESCRIPTION: Convert a list of values to an encoded bitmask + * + ******************************************************************************/ + +u16 acpi_rs_encode_bitmask(u8 * list, u8 count) +{ + u32 i; + u16 mask; + + ACPI_FUNCTION_ENTRY(); + + /* Encode the list into a single bitmask */ + + for (i = 0, mask = 0; i < count; i++) { + mask |= (0x1 << list[i]); + } + + return mask; +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_move_data + * + * PARAMETERS: Destination - Pointer to the destination descriptor + * Source - Pointer to the source descriptor + * item_count - How many items to move + * move_type - Byte width + * + * RETURN: None + * + * DESCRIPTION: Move multiple data items from one descriptor to another. Handles + * alignment issues and endian issues if necessary, as configured + * via the ACPI_MOVE_* macros. (This is why a memcpy is not used) + * + ******************************************************************************/ + +void +acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) +{ + u32 i; + + ACPI_FUNCTION_ENTRY(); + + /* One move per item */ + + for (i = 0; i < item_count; i++) { + switch (move_type) { + /* + * For the 8-bit case, we can perform the move all at once + * since there are no alignment or endian issues + */ + case ACPI_RSC_MOVE8: + ACPI_MEMCPY(destination, source, item_count); + return; + + /* + * 16-, 32-, and 64-bit cases must use the move macros that perform + * endian conversion and/or accomodate hardware that cannot perform + * misaligned memory transfers + */ + case ACPI_RSC_MOVE16: + ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i], + &ACPI_CAST_PTR(u16, source)[i]); + break; + + case ACPI_RSC_MOVE32: + ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i], + &ACPI_CAST_PTR(u32, source)[i]); + break; + + case ACPI_RSC_MOVE64: + ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i], + &ACPI_CAST_PTR(u64, source)[i]); + break; + + default: + return; + } + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_set_resource_length + * + * PARAMETERS: total_length - Length of the AML descriptor, including + * the header and length fields. + * Aml - Pointer to the raw AML descriptor + * + * RETURN: None + * + * DESCRIPTION: Set the resource_length field of an AML + * resource descriptor, both Large and Small descriptors are + * supported automatically. Note: Descriptor Type field must + * be valid. + * + ******************************************************************************/ + +void +acpi_rs_set_resource_length(acpi_rsdesc_size total_length, + union aml_resource *aml) +{ + acpi_rs_length resource_length; + + ACPI_FUNCTION_ENTRY(); + + /* Length is the total descriptor length minus the header length */ + + resource_length = (acpi_rs_length) + (total_length - acpi_ut_get_resource_header_length(aml)); + + /* Length is stored differently for large and small descriptors */ + + if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) { + + /* Large descriptor -- bytes 1-2 contain the 16-bit length */ + + ACPI_MOVE_16_TO_16(&aml->large_header.resource_length, + &resource_length); + } else { + /* Small descriptor -- bits 2:0 of byte 0 contain the length */ + + aml->small_header.descriptor_type = (u8) + + /* Clear any existing length, preserving descriptor type bits */ + ((aml->small_header. + descriptor_type & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK) + + | resource_length); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_set_resource_header + * + * PARAMETERS: descriptor_type - Byte to be inserted as the type + * total_length - Length of the AML descriptor, including + * the header and length fields. + * Aml - Pointer to the raw AML descriptor + * + * RETURN: None + * + * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML + * resource descriptor, both Large and Small descriptors are + * supported automatically + * + ******************************************************************************/ + +void +acpi_rs_set_resource_header(u8 descriptor_type, + acpi_rsdesc_size total_length, + union aml_resource *aml) +{ + ACPI_FUNCTION_ENTRY(); + + /* Set the Resource Type */ + + aml->small_header.descriptor_type = descriptor_type; + + /* Set the Resource Length */ + + acpi_rs_set_resource_length(total_length, aml); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_strcpy + * + * PARAMETERS: Destination - Pointer to the destination string + * Source - Pointer to the source string + * + * RETURN: String length, including NULL terminator + * + * DESCRIPTION: Local string copy that returns the string length, saving a + * strcpy followed by a strlen. + * + ******************************************************************************/ + +static u16 acpi_rs_strcpy(char *destination, char *source) +{ + u16 i; + + ACPI_FUNCTION_ENTRY(); + + for (i = 0; source[i]; i++) { + destination[i] = source[i]; + } + + destination[i] = 0; + + /* Return string length including the NULL terminator */ + + return ((u16) (i + 1)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_resource_source + * + * PARAMETERS: resource_length - Length field of the descriptor + * minimum_length - Minimum length of the descriptor (minus + * any optional fields) + * resource_source - Where the resource_source is returned + * Aml - Pointer to the raw AML descriptor + * string_ptr - (optional) where to store the actual + * resource_source string + * + * RETURN: Length of the string plus NULL terminator, rounded up to native + * word boundary + * + * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor + * to an internal resource descriptor + * + ******************************************************************************/ + +acpi_rs_length +acpi_rs_get_resource_source(acpi_rs_length resource_length, + acpi_rs_length minimum_length, + struct acpi_resource_source * resource_source, + union aml_resource * aml, char *string_ptr) +{ + acpi_rsdesc_size total_length; + u8 *aml_resource_source; + + ACPI_FUNCTION_ENTRY(); + + total_length = + resource_length + sizeof(struct aml_resource_large_header); + aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); + + /* + * resource_source is present if the length of the descriptor is longer than + * the minimum length. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the minimum length. + */ + if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) { + + /* Get the resource_source_index */ + + resource_source->index = aml_resource_source[0]; + + resource_source->string_ptr = string_ptr; + if (!string_ptr) { + /* + * String destination pointer is not specified; Set the String + * pointer to the end of the current resource_source structure. + */ + resource_source->string_ptr = + ACPI_ADD_PTR(char, resource_source, + sizeof(struct acpi_resource_source)); + } + + /* + * In order for the Resource length to be a multiple of the native + * word, calculate the length of the string (+1 for NULL terminator) + * and expand to the next word multiple. + * + * Zero the entire area of the buffer. + */ + total_length = (u32) + ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + 1; + total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); + + ACPI_MEMSET(resource_source->string_ptr, 0, total_length); + + /* Copy the resource_source string to the destination */ + + resource_source->string_length = + acpi_rs_strcpy(resource_source->string_ptr, + ACPI_CAST_PTR(char, + &aml_resource_source[1])); + + return ((acpi_rs_length) total_length); + } + + /* resource_source is not present */ + + resource_source->index = 0; + resource_source->string_length = 0; + resource_source->string_ptr = NULL; + return (0); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_set_resource_source + * + * PARAMETERS: Aml - Pointer to the raw AML descriptor + * minimum_length - Minimum length of the descriptor (minus + * any optional fields) + * resource_source - Internal resource_source + + * + * RETURN: Total length of the AML descriptor + * + * DESCRIPTION: Convert an optional resource_source from internal format to a + * raw AML resource descriptor + * + ******************************************************************************/ + +acpi_rsdesc_size +acpi_rs_set_resource_source(union aml_resource * aml, + acpi_rs_length minimum_length, + struct acpi_resource_source * resource_source) +{ + u8 *aml_resource_source; + acpi_rsdesc_size descriptor_length; + + ACPI_FUNCTION_ENTRY(); + + descriptor_length = minimum_length; + + /* Non-zero string length indicates presence of a resource_source */ + + if (resource_source->string_length) { + + /* Point to the end of the AML descriptor */ + + aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); + + /* Copy the resource_source_index */ + + aml_resource_source[0] = (u8) resource_source->index; + + /* Copy the resource_source string */ + + ACPI_STRCPY(ACPI_CAST_PTR(char, &aml_resource_source[1]), + resource_source->string_ptr); + + /* + * Add the length of the string (+ 1 for null terminator) to the + * final descriptor length + */ + descriptor_length += + ((acpi_rsdesc_size) resource_source->string_length + 1); + } + + /* Return the new total length of the AML descriptor */ + + return (descriptor_length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_prt_method_data + * + * PARAMETERS: Node - Device node + * ret_buffer - Pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _PRT value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_prt_method_data(struct acpi_namespace_node * node, + struct acpi_buffer * ret_buffer) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(rs_get_prt_method_data); + + /* Parameters guaranteed valid by caller */ + + /* Execute the method, no parameters */ + + status = acpi_ut_evaluate_object(node, METHOD_NAME__PRT, + ACPI_BTYPE_PACKAGE, &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Create a resource linked list from the byte stream buffer that comes + * back from the _CRS method execution. + */ + status = acpi_rs_create_pci_routing_table(obj_desc, ret_buffer); + + /* On exit, we must delete the object returned by evaluate_object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_crs_method_data + * + * PARAMETERS: Node - Device node + * ret_buffer - Pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _CRS value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_crs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *ret_buffer) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(rs_get_crs_method_data); + + /* Parameters guaranteed valid by caller */ + + /* Execute the method, no parameters */ + + status = acpi_ut_evaluate_object(node, METHOD_NAME__CRS, + ACPI_BTYPE_BUFFER, &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + status = acpi_rs_create_resource_list(obj_desc, ret_buffer); + + /* On exit, we must delete the object returned by evaluate_object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_prs_method_data + * + * PARAMETERS: Node - Device node + * ret_buffer - Pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _PRS value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +#ifdef ACPI_FUTURE_USAGE +acpi_status +acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *ret_buffer) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(rs_get_prs_method_data); + + /* Parameters guaranteed valid by caller */ + + /* Execute the method, no parameters */ + + status = acpi_ut_evaluate_object(node, METHOD_NAME__PRS, + ACPI_BTYPE_BUFFER, &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + status = acpi_rs_create_resource_list(obj_desc, ret_buffer); + + /* On exit, we must delete the object returned by evaluate_object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} +#endif /* ACPI_FUTURE_USAGE */ + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_method_data + * + * PARAMETERS: Handle - Handle to the containing object + * Path - Path to method, relative to Handle + * ret_buffer - Pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _CRS or _PRS value of an + * object contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_method_data(acpi_handle handle, + char *path, struct acpi_buffer *ret_buffer) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(rs_get_method_data); + + /* Parameters guaranteed valid by caller */ + + /* Execute the method, no parameters */ + + status = + acpi_ut_evaluate_object(handle, path, ACPI_BTYPE_BUFFER, &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the method + * execution. + */ + status = acpi_rs_create_resource_list(obj_desc, ret_buffer); + + /* On exit, we must delete the object returned by evaluate_object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_set_srs_method_data + * + * PARAMETERS: Node - Device node + * in_buffer - Pointer to a buffer structure of the + * parameter + * + * RETURN: Status + * + * DESCRIPTION: This function is called to set the _SRS of an object contained + * in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + * Note: Parameters guaranteed valid by caller + * + ******************************************************************************/ + +acpi_status +acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *in_buffer) +{ + struct acpi_evaluate_info *info; + union acpi_operand_object *args[2]; + acpi_status status; + struct acpi_buffer buffer; + + ACPI_FUNCTION_TRACE(rs_set_srs_method_data); + + /* Allocate and initialize the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->prefix_node = node; + info->pathname = METHOD_NAME__SRS; + info->parameters = args; + info->flags = ACPI_IGNORE_RETURN_VALUE; + + /* + * The in_buffer parameter will point to a linked list of + * resource parameters. It needs to be formatted into a + * byte stream to be sent in as an input parameter to _SRS + * + * Convert the linked list into a byte stream + */ + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Create and initialize the method parameter object */ + + args[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); + if (!args[0]) { + /* + * Must free the buffer allocated above (otherwise it is freed + * later) + */ + ACPI_FREE(buffer.pointer); + status = AE_NO_MEMORY; + goto cleanup; + } + + args[0]->buffer.length = (u32) buffer.length; + args[0]->buffer.pointer = buffer.pointer; + args[0]->common.flags = AOPOBJ_DATA_VALID; + args[1] = NULL; + + /* Execute the method, no return value is expected */ + + status = acpi_ns_evaluate(info); + + /* Clean up and return the status from acpi_ns_evaluate */ + + acpi_ut_remove_reference(args[0]); + + cleanup: + ACPI_FREE(info); + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c new file mode 100644 index 000000000000..0a274356b23e --- /dev/null +++ b/drivers/acpi/acpica/rsxface.c @@ -0,0 +1,571 @@ +/******************************************************************************* + * + * Module Name: rsxface - Public interfaces to the resource manager + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsxface") + +/* Local macros for 16,32-bit to 64-bit conversion */ +#define ACPI_COPY_FIELD(out, in, field) ((out)->field = (in)->field) +#define ACPI_COPY_ADDRESS(out, in) \ + ACPI_COPY_FIELD(out, in, resource_type); \ + ACPI_COPY_FIELD(out, in, producer_consumer); \ + ACPI_COPY_FIELD(out, in, decode); \ + ACPI_COPY_FIELD(out, in, min_address_fixed); \ + ACPI_COPY_FIELD(out, in, max_address_fixed); \ + ACPI_COPY_FIELD(out, in, info); \ + ACPI_COPY_FIELD(out, in, granularity); \ + ACPI_COPY_FIELD(out, in, minimum); \ + ACPI_COPY_FIELD(out, in, maximum); \ + ACPI_COPY_FIELD(out, in, translation_offset); \ + ACPI_COPY_FIELD(out, in, address_length); \ + ACPI_COPY_FIELD(out, in, resource_source); +/* Local prototypes */ +static acpi_status +acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context); + +static acpi_status +acpi_rs_validate_parameters(acpi_handle device_handle, + struct acpi_buffer *buffer, + struct acpi_namespace_node **return_node); + +/******************************************************************************* + * + * FUNCTION: acpi_rs_validate_parameters + * + * PARAMETERS: device_handle - Handle to a device + * Buffer - Pointer to a data buffer + * return_node - Pointer to where the device node is returned + * + * RETURN: Status + * + * DESCRIPTION: Common parameter validation for resource interfaces + * + ******************************************************************************/ + +static acpi_status +acpi_rs_validate_parameters(acpi_handle device_handle, + struct acpi_buffer *buffer, + struct acpi_namespace_node **return_node) +{ + acpi_status status; + struct acpi_namespace_node *node; + + ACPI_FUNCTION_TRACE(rs_validate_parameters); + + /* + * Must have a valid handle to an ACPI device + */ + if (!device_handle) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + node = acpi_ns_map_handle_to_node(device_handle); + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (node->type != ACPI_TYPE_DEVICE) { + return_ACPI_STATUS(AE_TYPE); + } + + /* + * Validate the user buffer object + * + * if there is a non-zero buffer length we also need a valid pointer in + * the buffer. If it's a zero buffer length, we'll be returning the + * needed buffer size (later), so keep going. + */ + status = acpi_ut_validate_buffer(buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + *return_node = node; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_get_irq_routing_table + * + * PARAMETERS: device_handle - Handle to the Bus device we are querying + * ret_buffer - Pointer to a buffer to receive the + * current resources for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the IRQ routing table for a + * specific bus. The caller must first acquire a handle for the + * desired bus. The routine table is placed in the buffer pointed + * to by the ret_buffer variable parameter. + * + * If the function fails an appropriate status will be returned + * and the value of ret_buffer is undefined. + * + * This function attempts to execute the _PRT method contained in + * the object indicated by the passed device_handle. + * + ******************************************************************************/ + +acpi_status +acpi_get_irq_routing_table(acpi_handle device_handle, + struct acpi_buffer *ret_buffer) +{ + acpi_status status; + struct acpi_namespace_node *node; + + ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table); + + /* Validate parameters then dispatch to internal routine */ + + status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_rs_get_prt_method_data(node, ret_buffer); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table) + +/******************************************************************************* + * + * FUNCTION: acpi_get_current_resources + * + * PARAMETERS: device_handle - Handle to the device object for the + * device we are querying + * ret_buffer - Pointer to a buffer to receive the + * current resources for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the current resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is placed in the buffer + * pointed to by the ret_buffer variable parameter. + * + * If the function fails an appropriate status will be returned + * and the value of ret_buffer is undefined. + * + * This function attempts to execute the _CRS method contained in + * the object indicated by the passed device_handle. + * + ******************************************************************************/ +acpi_status +acpi_get_current_resources(acpi_handle device_handle, + struct acpi_buffer *ret_buffer) +{ + acpi_status status; + struct acpi_namespace_node *node; + + ACPI_FUNCTION_TRACE(acpi_get_current_resources); + + /* Validate parameters then dispatch to internal routine */ + + status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_rs_get_crs_method_data(node, ret_buffer); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_current_resources) +#ifdef ACPI_FUTURE_USAGE +/******************************************************************************* + * + * FUNCTION: acpi_get_possible_resources + * + * PARAMETERS: device_handle - Handle to the device object for the + * device we are querying + * ret_buffer - Pointer to a buffer to receive the + * resources for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get a list of the possible resources + * for a specific device. The caller must first acquire a handle + * for the desired device. The resource data is placed in the + * buffer pointed to by the ret_buffer variable. + * + * If the function fails an appropriate status will be returned + * and the value of ret_buffer is undefined. + * + ******************************************************************************/ +acpi_status +acpi_get_possible_resources(acpi_handle device_handle, + struct acpi_buffer *ret_buffer) +{ + acpi_status status; + struct acpi_namespace_node *node; + + ACPI_FUNCTION_TRACE(acpi_get_possible_resources); + + /* Validate parameters then dispatch to internal routine */ + + status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_rs_get_prs_method_data(node, ret_buffer); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_possible_resources) +#endif /* ACPI_FUTURE_USAGE */ +/******************************************************************************* + * + * FUNCTION: acpi_set_current_resources + * + * PARAMETERS: device_handle - Handle to the device object for the + * device we are setting resources + * in_buffer - Pointer to a buffer containing the + * resources to be set for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to set the current resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is passed to the routine + * the buffer pointed to by the in_buffer variable. + * + ******************************************************************************/ +acpi_status +acpi_set_current_resources(acpi_handle device_handle, + struct acpi_buffer *in_buffer) +{ + acpi_status status; + struct acpi_namespace_node *node; + + ACPI_FUNCTION_TRACE(acpi_set_current_resources); + + /* Validate the buffer, don't allow zero length */ + + if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Validate parameters then dispatch to internal routine */ + + status = acpi_rs_validate_parameters(device_handle, in_buffer, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_rs_set_srs_method_data(node, in_buffer); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_set_current_resources) + +/****************************************************************************** + * + * FUNCTION: acpi_resource_to_address64 + * + * PARAMETERS: Resource - Pointer to a resource + * Out - Pointer to the users's return buffer + * (a struct acpi_resource_address64) + * + * RETURN: Status + * + * DESCRIPTION: If the resource is an address16, address32, or address64, + * copy it to the address64 return buffer. This saves the + * caller from having to duplicate code for different-sized + * addresses. + * + ******************************************************************************/ +acpi_status +acpi_resource_to_address64(struct acpi_resource *resource, + struct acpi_resource_address64 *out) +{ + struct acpi_resource_address16 *address16; + struct acpi_resource_address32 *address32; + + if (!resource || !out) { + return (AE_BAD_PARAMETER); + } + + /* Convert 16 or 32 address descriptor to 64 */ + + switch (resource->type) { + case ACPI_RESOURCE_TYPE_ADDRESS16: + + address16 = (struct acpi_resource_address16 *)&resource->data; + ACPI_COPY_ADDRESS(out, address16); + break; + + case ACPI_RESOURCE_TYPE_ADDRESS32: + + address32 = (struct acpi_resource_address32 *)&resource->data; + ACPI_COPY_ADDRESS(out, address32); + break; + + case ACPI_RESOURCE_TYPE_ADDRESS64: + + /* Simple copy for 64 bit source */ + + ACPI_MEMCPY(out, &resource->data, + sizeof(struct acpi_resource_address64)); + break; + + default: + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_resource_to_address64) + +/******************************************************************************* + * + * FUNCTION: acpi_get_vendor_resource + * + * PARAMETERS: device_handle - Handle for the parent device object + * Name - Method name for the parent resource + * (METHOD_NAME__CRS or METHOD_NAME__PRS) + * Uuid - Pointer to the UUID to be matched. + * includes both subtype and 16-byte UUID + * ret_buffer - Where the vendor resource is returned + * + * RETURN: Status + * + * DESCRIPTION: Walk a resource template for the specified evice to find a + * vendor-defined resource that matches the supplied UUID and + * UUID subtype. Returns a struct acpi_resource of type Vendor. + * + ******************************************************************************/ +acpi_status +acpi_get_vendor_resource(acpi_handle device_handle, + char *name, + struct acpi_vendor_uuid * uuid, + struct acpi_buffer * ret_buffer) +{ + struct acpi_vendor_walk_info info; + acpi_status status; + + /* Other parameters are validated by acpi_walk_resources */ + + if (!uuid || !ret_buffer) { + return (AE_BAD_PARAMETER); + } + + info.uuid = uuid; + info.buffer = ret_buffer; + info.status = AE_NOT_EXIST; + + /* Walk the _CRS or _PRS resource list for this device */ + + status = + acpi_walk_resources(device_handle, name, + acpi_rs_match_vendor_resource, &info); + if (ACPI_FAILURE(status)) { + return (status); + } + + return (info.status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource) + +/******************************************************************************* + * + * FUNCTION: acpi_rs_match_vendor_resource + * + * PARAMETERS: acpi_walk_resource_callback + * + * RETURN: Status + * + * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID + * + ******************************************************************************/ +static acpi_status +acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) +{ + struct acpi_vendor_walk_info *info = context; + struct acpi_resource_vendor_typed *vendor; + struct acpi_buffer *buffer; + acpi_status status; + + /* Ignore all descriptors except Vendor */ + + if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) { + return (AE_OK); + } + + vendor = &resource->data.vendor_typed; + + /* + * For a valid match, these conditions must hold: + * + * 1) Length of descriptor data must be at least as long as a UUID struct + * 2) The UUID subtypes must match + * 3) The UUID data must match + */ + if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) || + (vendor->uuid_subtype != info->uuid->subtype) || + (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) { + return (AE_OK); + } + + /* Validate/Allocate/Clear caller buffer */ + + buffer = info->buffer; + status = acpi_ut_initialize_buffer(buffer, resource->length); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Found the correct resource, copy and return it */ + + ACPI_MEMCPY(buffer->pointer, resource, resource->length); + buffer->length = resource->length; + + /* Found the desired descriptor, terminate resource walk */ + + info->status = AE_OK; + return (AE_CTRL_TERMINATE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_walk_resources + * + * PARAMETERS: device_handle - Handle to the device object for the + * device we are querying + * Name - Method name of the resources we want + * (METHOD_NAME__CRS or METHOD_NAME__PRS) + * user_function - Called for each resource + * Context - Passed to user_function + * + * RETURN: Status + * + * DESCRIPTION: Retrieves the current or possible resource list for the + * specified device. The user_function is called once for + * each resource in the list. + * + ******************************************************************************/ +acpi_status +acpi_walk_resources(acpi_handle device_handle, + char *name, + acpi_walk_resource_callback user_function, void *context) +{ + acpi_status status; + struct acpi_buffer buffer; + struct acpi_resource *resource; + struct acpi_resource *resource_end; + + ACPI_FUNCTION_TRACE(acpi_walk_resources); + + /* Parameter validation */ + + if (!device_handle || !user_function || !name || + (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && + !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the _CRS or _PRS resource list */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_rs_get_method_data(device_handle, name, &buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Buffer now contains the resource list */ + + resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); + resource_end = + ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); + + /* Walk the resource list until the end_tag is found (or buffer end) */ + + while (resource < resource_end) { + + /* Sanity check the resource */ + + if (resource->type > ACPI_RESOURCE_TYPE_MAX) { + status = AE_AML_INVALID_RESOURCE_TYPE; + break; + } + + /* Invoke the user function, abort on any error returned */ + + status = user_function(resource, context); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_TERMINATE) { + + /* This is an OK termination by the user function */ + + status = AE_OK; + } + break; + } + + /* end_tag indicates end-of-list */ + + if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { + break; + } + + /* Get the next resource descriptor */ + + resource = + ACPI_ADD_PTR(struct acpi_resource, resource, + resource->length); + } + + ACPI_FREE(buffer.pointer); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_walk_resources) diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c new file mode 100644 index 000000000000..87f22e68c6d6 --- /dev/null +++ b/drivers/acpi/acpica/tbfadt.c @@ -0,0 +1,610 @@ +/****************************************************************************** + * + * Module Name: tbfadt - FADT table utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbfadt") + +/* Local prototypes */ +static inline void +acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, + u8 space_id, u8 byte_width, u64 address); + +static void acpi_tb_convert_fadt(void); + +static void acpi_tb_validate_fadt(void); + +/* Table for conversion of FADT to common internal format and FADT validation */ + +typedef struct acpi_fadt_info { + char *name; + u8 address64; + u8 address32; + u8 length; + u8 default_length; + u8 type; + +} acpi_fadt_info; + +#define ACPI_FADT_REQUIRED 1 +#define ACPI_FADT_SEPARATE_LENGTH 2 + +static struct acpi_fadt_info fadt_info_table[] = { + {"Pm1aEventBlock", + ACPI_FADT_OFFSET(xpm1a_event_block), + ACPI_FADT_OFFSET(pm1a_event_block), + ACPI_FADT_OFFSET(pm1_event_length), + ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ + ACPI_FADT_REQUIRED}, + + {"Pm1bEventBlock", + ACPI_FADT_OFFSET(xpm1b_event_block), + ACPI_FADT_OFFSET(pm1b_event_block), + ACPI_FADT_OFFSET(pm1_event_length), + ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ + 0}, + + {"Pm1aControlBlock", + ACPI_FADT_OFFSET(xpm1a_control_block), + ACPI_FADT_OFFSET(pm1a_control_block), + ACPI_FADT_OFFSET(pm1_control_length), + ACPI_PM1_REGISTER_WIDTH, + ACPI_FADT_REQUIRED}, + + {"Pm1bControlBlock", + ACPI_FADT_OFFSET(xpm1b_control_block), + ACPI_FADT_OFFSET(pm1b_control_block), + ACPI_FADT_OFFSET(pm1_control_length), + ACPI_PM1_REGISTER_WIDTH, + 0}, + + {"Pm2ControlBlock", + ACPI_FADT_OFFSET(xpm2_control_block), + ACPI_FADT_OFFSET(pm2_control_block), + ACPI_FADT_OFFSET(pm2_control_length), + ACPI_PM2_REGISTER_WIDTH, + ACPI_FADT_SEPARATE_LENGTH}, + + {"PmTimerBlock", + ACPI_FADT_OFFSET(xpm_timer_block), + ACPI_FADT_OFFSET(pm_timer_block), + ACPI_FADT_OFFSET(pm_timer_length), + ACPI_PM_TIMER_WIDTH, + ACPI_FADT_REQUIRED}, + + {"Gpe0Block", + ACPI_FADT_OFFSET(xgpe0_block), + ACPI_FADT_OFFSET(gpe0_block), + ACPI_FADT_OFFSET(gpe0_block_length), + 0, + ACPI_FADT_SEPARATE_LENGTH}, + + {"Gpe1Block", + ACPI_FADT_OFFSET(xgpe1_block), + ACPI_FADT_OFFSET(gpe1_block), + ACPI_FADT_OFFSET(gpe1_block_length), + 0, + ACPI_FADT_SEPARATE_LENGTH} +}; + +#define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) + +/******************************************************************************* + * + * FUNCTION: acpi_tb_init_generic_address + * + * PARAMETERS: generic_address - GAS struct to be initialized + * byte_width - Width of this register + * Address - Address of the register + * + * RETURN: None + * + * DESCRIPTION: Initialize a Generic Address Structure (GAS) + * See the ACPI specification for a full description and + * definition of this structure. + * + ******************************************************************************/ + +static inline void +acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, + u8 space_id, u8 byte_width, u64 address) +{ + + /* + * The 64-bit Address field is non-aligned in the byte packed + * GAS struct. + */ + ACPI_MOVE_64_TO_64(&generic_address->address, &address); + + /* All other fields are byte-wide */ + + generic_address->space_id = space_id; + generic_address->bit_width = (u8)ACPI_MUL_8(byte_width); + generic_address->bit_offset = 0; + generic_address->access_width = 0; /* Access width ANY */ +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_parse_fadt + * + * PARAMETERS: table_index - Index for the FADT + * Flags - Flags + * + * RETURN: None + * + * DESCRIPTION: Initialize the FADT, DSDT and FACS tables + * (FADT contains the addresses of the DSDT and FACS) + * + ******************************************************************************/ + +void acpi_tb_parse_fadt(u32 table_index, u8 flags) +{ + u32 length; + struct acpi_table_header *table; + + /* + * The FADT has multiple versions with different lengths, + * and it contains pointers to both the DSDT and FACS tables. + * + * Get a local copy of the FADT and convert it to a common format + * Map entire FADT, assumed to be smaller than one page. + */ + length = acpi_gbl_root_table_list.tables[table_index].length; + + table = + acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index]. + address, length); + if (!table) { + return; + } + + /* + * Validate the FADT checksum before we copy the table. Ignore + * checksum error as we want to try to get the DSDT and FACS. + */ + (void)acpi_tb_verify_checksum(table, length); + + /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ + + acpi_tb_create_local_fadt(table, length); + + /* All done with the real FADT, unmap it */ + + acpi_os_unmap_memory(table, length); + + /* Obtain the DSDT and FACS tables via their addresses within the FADT */ + + acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, + flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); + + acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, + flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_create_local_fadt + * + * PARAMETERS: Table - Pointer to BIOS FADT + * Length - Length of the table + * + * RETURN: None + * + * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. + * Performs validation on some important FADT fields. + * + * NOTE: We create a local copy of the FADT regardless of the version. + * + ******************************************************************************/ + +void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) +{ + + /* + * Check if the FADT is larger than the largest table that we expect + * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue + * a warning. + */ + if (length > sizeof(struct acpi_table_fadt)) { + ACPI_WARNING((AE_INFO, + "FADT (revision %u) is longer than ACPI 2.0 version, " + "truncating length 0x%X to 0x%zX", + table->revision, (unsigned)length, + sizeof(struct acpi_table_fadt))); + } + + /* Clear the entire local FADT */ + + ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); + + /* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */ + + ACPI_MEMCPY(&acpi_gbl_FADT, table, + ACPI_MIN(length, sizeof(struct acpi_table_fadt))); + + /* + * 1) Convert the local copy of the FADT to the common internal format + * 2) Validate some of the important values within the FADT + */ + acpi_tb_convert_fadt(); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_convert_fadt + * + * PARAMETERS: None, uses acpi_gbl_FADT + * + * RETURN: None + * + * DESCRIPTION: Converts all versions of the FADT to a common internal format. + * Expand all 32-bit addresses to 64-bit. + * + * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), + * and must contain a copy of the actual FADT. + * + * ACPICA will use the "X" fields of the FADT for all addresses. + * + * "X" fields are optional extensions to the original V1.0 fields. Even if + * they are present in the structure, they can be optionally not used by + * setting them to zero. Therefore, we must selectively expand V1.0 fields + * if the corresponding X field is zero. + * + * For ACPI 1.0 FADTs, all address fields are expanded to the corresponding + * "X" fields. + * + * For ACPI 2.0 FADTs, any "X" fields that are NULL are filled in by + * expanding the corresponding ACPI 1.0 field. + * + ******************************************************************************/ + +static void acpi_tb_convert_fadt(void) +{ + u8 pm1_register_bit_width; + u8 pm1_register_byte_width; + struct acpi_generic_address *target64; + u32 i; + + /* Update the local FADT table header length */ + + acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); + + /* + * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. + * Later code will always use the X 64-bit field. Also, check for an + * address mismatch between the 32-bit and 64-bit address fields + * (FIRMWARE_CTRL/X_FIRMWARE_CTRL, DSDT/X_DSDT) which would indicate + * the presence of two FACS or two DSDT tables. + */ + if (!acpi_gbl_FADT.Xfacs) { + acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; + } else if (acpi_gbl_FADT.facs && + (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) { + ACPI_WARNING((AE_INFO, + "32/64 FACS address mismatch in FADT - two FACS tables!")); + } + + if (!acpi_gbl_FADT.Xdsdt) { + acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; + } else if (acpi_gbl_FADT.dsdt && + (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) { + ACPI_WARNING((AE_INFO, + "32/64 DSDT address mismatch in FADT - two DSDT tables!")); + } + + /* + * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which + * should be zero are indeed zero. This will workaround BIOSs that + * inadvertently place values in these fields. + * + * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at + * offset 45, 55, 95, and the word located at offset 109, 110. + */ + if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) { + acpi_gbl_FADT.preferred_profile = 0; + acpi_gbl_FADT.pstate_control = 0; + acpi_gbl_FADT.cst_control = 0; + acpi_gbl_FADT.boot_flags = 0; + } + + /* + * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" + * generic address structures as necessary. Later code will always use + * the 64-bit address structures. + */ + for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { + target64 = + ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, + fadt_info_table[i].address64); + + /* Expand only if the 64-bit X target is null */ + + if (!target64->address) { + + /* The space_id is always I/O for the 32-bit legacy address fields */ + + acpi_tb_init_generic_address(target64, + ACPI_ADR_SPACE_SYSTEM_IO, + *ACPI_ADD_PTR(u8, + &acpi_gbl_FADT, + fadt_info_table + [i].length), + (u64) * ACPI_ADD_PTR(u32, + &acpi_gbl_FADT, + fadt_info_table + [i]. + address32)); + } + } + + /* Validate FADT values now, before we make any changes */ + + acpi_tb_validate_fadt(); + + /* + * Optionally check all register lengths against the default values and + * update them if they are incorrect. + */ + if (acpi_gbl_use_default_register_widths) { + for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { + target64 = + ACPI_ADD_PTR(struct acpi_generic_address, + &acpi_gbl_FADT, + fadt_info_table[i].address64); + + /* + * If a valid register (Address != 0) and the (default_length > 0) + * (Not a GPE register), then check the width against the default. + */ + if ((target64->address) && + (fadt_info_table[i].default_length > 0) && + (fadt_info_table[i].default_length != + target64->bit_width)) { + ACPI_WARNING((AE_INFO, + "Invalid length for %s: %d, using default %d", + fadt_info_table[i].name, + target64->bit_width, + fadt_info_table[i]. + default_length)); + + /* Incorrect size, set width to the default */ + + target64->bit_width = + fadt_info_table[i].default_length; + } + } + } + + /* + * Get the length of the individual PM1 registers (enable and status). + * Each register is defined to be (event block length / 2). + */ + pm1_register_bit_width = + (u8)ACPI_DIV_2(acpi_gbl_FADT.xpm1a_event_block.bit_width); + pm1_register_byte_width = (u8)ACPI_DIV_8(pm1_register_bit_width); + + /* + * Adjust the lengths of the PM1 Event Blocks so that they can be used to + * access the PM1 status register(s). Use (width / 2) + */ + acpi_gbl_FADT.xpm1a_event_block.bit_width = pm1_register_bit_width; + acpi_gbl_FADT.xpm1b_event_block.bit_width = pm1_register_bit_width; + + /* + * Calculate separate GAS structs for the PM1 Enable registers. + * These addresses do not appear (directly) in the FADT, so it is + * useful to calculate them once, here. + * + * The PM event blocks are split into two register blocks, first is the + * PM Status Register block, followed immediately by the PM Enable + * Register block. Each is of length (xpm1x_event_block.bit_width/2). + * + * On various systems the v2 fields (and particularly the bit widths) + * cannot be relied upon, though. Hence resort to using the v1 length + * here (and warn about the inconsistency). + */ + if (acpi_gbl_FADT.xpm1a_event_block.bit_width + != acpi_gbl_FADT.pm1_event_length * 8) + printk(KERN_WARNING "FADT: " + "X_PM1a_EVT_BLK.bit_width (%u) does not match" + " PM1_EVT_LEN (%u)\n", + acpi_gbl_FADT.xpm1a_event_block.bit_width, + acpi_gbl_FADT.pm1_event_length); + + /* The PM1A register block is required */ + + acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, + acpi_gbl_FADT.xpm1a_event_block.space_id, + pm1_register_byte_width, + (acpi_gbl_FADT.xpm1a_event_block.address + + pm1_register_byte_width)); + /* Don't forget to copy space_id of the GAS */ + acpi_gbl_xpm1a_enable.space_id = + acpi_gbl_FADT.xpm1a_event_block.space_id; + + /* The PM1B register block is optional, ignore if not present */ + + if (acpi_gbl_FADT.xpm1b_event_block.address) { + if (acpi_gbl_FADT.xpm1b_event_block.bit_width + != acpi_gbl_FADT.pm1_event_length * 8) + printk(KERN_WARNING "FADT: " + "X_PM1b_EVT_BLK.bit_width (%u) does not match" + " PM1_EVT_LEN (%u)\n", + acpi_gbl_FADT.xpm1b_event_block.bit_width, + acpi_gbl_FADT.pm1_event_length); + acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, + acpi_gbl_FADT.xpm1b_event_block.space_id, + pm1_register_byte_width, + (acpi_gbl_FADT.xpm1b_event_block. + address + pm1_register_byte_width)); + /* Don't forget to copy space_id of the GAS */ + acpi_gbl_xpm1b_enable.space_id = + acpi_gbl_FADT.xpm1b_event_block.space_id; + + } +} + +/****************************************************************************** + * + * FUNCTION: acpi_tb_validate_fadt + * + * PARAMETERS: Table - Pointer to the FADT to be validated + * + * RETURN: None + * + * DESCRIPTION: Validate various important fields within the FADT. If a problem + * is found, issue a message, but no status is returned. + * Used by both the table manager and the disassembler. + * + * Possible additional checks: + * (acpi_gbl_FADT.pm1_event_length >= 4) + * (acpi_gbl_FADT.pm1_control_length >= 2) + * (acpi_gbl_FADT.pm_timer_length >= 4) + * Gpe block lengths must be multiple of 2 + * + ******************************************************************************/ + +static void acpi_tb_validate_fadt(void) +{ + char *name; + u32 *address32; + struct acpi_generic_address *address64; + u8 length; + u32 i; + + /* + * Check for FACS and DSDT address mismatches. An address mismatch between + * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and + * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables. + */ + if (acpi_gbl_FADT.facs && + (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) { + ACPI_WARNING((AE_INFO, + "32/64X FACS address mismatch in FADT - " + "two FACS tables! %8.8X/%8.8X%8.8X", + acpi_gbl_FADT.facs, + ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs))); + } + + if (acpi_gbl_FADT.dsdt && + (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) { + ACPI_WARNING((AE_INFO, + "32/64X DSDT address mismatch in FADT - " + "two DSDT tables! %8.8X/%8.8X%8.8X", + acpi_gbl_FADT.dsdt, + ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt))); + } + + /* Examine all of the 64-bit extended address fields (X fields) */ + + for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { + /* + * Generate pointers to the 32-bit and 64-bit addresses, get the + * register length (width), and the register name + */ + address64 = ACPI_ADD_PTR(struct acpi_generic_address, + &acpi_gbl_FADT, + fadt_info_table[i].address64); + address32 = + ACPI_ADD_PTR(u32, &acpi_gbl_FADT, + fadt_info_table[i].address32); + length = + *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, + fadt_info_table[i].length); + name = fadt_info_table[i].name; + + /* + * For each extended field, check for length mismatch between the + * legacy length field and the corresponding 64-bit X length field. + */ + if (address64 && (address64->bit_width != ACPI_MUL_8(length))) { + ACPI_WARNING((AE_INFO, + "32/64X length mismatch in %s: %d/%d", + name, ACPI_MUL_8(length), + address64->bit_width)); + } + + if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) { + /* + * Field is required (Pm1a_event, Pm1a_control, pm_timer). + * Both the address and length must be non-zero. + */ + if (!address64->address || !length) { + ACPI_ERROR((AE_INFO, + "Required field %s has zero address and/or length: %8.8X%8.8X/%X", + name, + ACPI_FORMAT_UINT64(address64-> + address), + length)); + } + } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { + /* + * Field is optional (PM2Control, GPE0, GPE1) AND has its own + * length field. If present, both the address and length must be valid. + */ + if ((address64->address && !length) + || (!address64->address && length)) { + ACPI_WARNING((AE_INFO, + "Optional field %s has zero address or length: %8.8X%8.8X/%X", + name, + ACPI_FORMAT_UINT64(address64-> + address), + length)); + } + } + + /* If both 32- and 64-bit addresses are valid (non-zero), they must match */ + + if (address64->address && *address32 && + (address64->address != (u64) * address32)) { + ACPI_ERROR((AE_INFO, + "32/64X address mismatch in %s: %8.8X/%8.8X%8.8X, using 64X", + name, *address32, + ACPI_FORMAT_UINT64(address64->address))); + } + } +} diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c new file mode 100644 index 000000000000..9d20cb6db892 --- /dev/null +++ b/drivers/acpi/acpica/tbfind.c @@ -0,0 +1,140 @@ +/****************************************************************************** + * + * Module Name: tbfind - find table + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbfind") + +/******************************************************************************* + * + * FUNCTION: acpi_tb_find_table + * + * PARAMETERS: Signature - String with ACPI table signature + * oem_id - String with the table OEM ID + * oem_table_id - String with the OEM Table ID + * table_index - Where the table index is returned + * + * RETURN: Status and table index + * + * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the + * Signature, OEM ID and OEM Table ID. Returns an index that can + * be used to get the table header or entire table. + * + ******************************************************************************/ +acpi_status +acpi_tb_find_table(char *signature, + char *oem_id, char *oem_table_id, u32 *table_index) +{ + u32 i; + acpi_status status; + struct acpi_table_header header; + + ACPI_FUNCTION_TRACE(tb_find_table); + + /* Normalize the input strings */ + + ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header)); + ACPI_STRNCPY(header.signature, signature, ACPI_NAME_SIZE); + ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE); + ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE); + + /* Search for the table */ + + for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { + if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature), + header.signature, ACPI_NAME_SIZE)) { + + /* Not the requested table */ + + continue; + } + + /* Table with matching signature has been found */ + + if (!acpi_gbl_root_table_list.tables[i].pointer) { + + /* Table is not currently mapped, map it */ + + status = + acpi_tb_verify_table(&acpi_gbl_root_table_list. + tables[i]); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (!acpi_gbl_root_table_list.tables[i].pointer) { + continue; + } + } + + /* Check for table match on all IDs */ + + if (!ACPI_MEMCMP + (acpi_gbl_root_table_list.tables[i].pointer->signature, + header.signature, ACPI_NAME_SIZE) && (!oem_id[0] + || + !ACPI_MEMCMP + (acpi_gbl_root_table_list. + tables[i].pointer-> + oem_id, + header.oem_id, + ACPI_OEM_ID_SIZE)) + && (!oem_table_id[0] + || !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i]. + pointer->oem_table_id, + header.oem_table_id, + ACPI_OEM_TABLE_ID_SIZE))) { + *table_index = i; + + ACPI_DEBUG_PRINT((ACPI_DB_TABLES, + "Found table [%4.4s]\n", + header.signature)); + return_ACPI_STATUS(AE_OK); + } + } + + return_ACPI_STATUS(AE_NOT_FOUND); +} diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c new file mode 100644 index 000000000000..019b0d84cbea --- /dev/null +++ b/drivers/acpi/acpica/tbinstal.c @@ -0,0 +1,574 @@ +/****************************************************************************** + * + * Module Name: tbinstal - ACPI table installation and removal + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbinstal") + +/****************************************************************************** + * + * FUNCTION: acpi_tb_verify_table + * + * PARAMETERS: table_desc - table + * + * RETURN: Status + * + * DESCRIPTION: this function is called to verify and map table + * + *****************************************************************************/ +acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(tb_verify_table); + + /* Map the table if necessary */ + + if (!table_desc->pointer) { + if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == + ACPI_TABLE_ORIGIN_MAPPED) { + table_desc->pointer = + acpi_os_map_memory(table_desc->address, + table_desc->length); + } + if (!table_desc->pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + } + + /* FACS is the odd table, has no standard ACPI header and no checksum */ + + if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) { + + /* Always calculate checksum, ignore bad checksum if requested */ + + status = + acpi_tb_verify_checksum(table_desc->pointer, + table_desc->length); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_add_table + * + * PARAMETERS: table_desc - Table descriptor + * table_index - Where the table index is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to add the ACPI table + * + ******************************************************************************/ + +acpi_status +acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) +{ + u32 i; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(tb_add_table); + + if (!table_desc->pointer) { + status = acpi_tb_verify_table(table_desc); + if (ACPI_FAILURE(status) || !table_desc->pointer) { + return_ACPI_STATUS(status); + } + } + + /* + * Originally, we checked the table signature for "SSDT" or "PSDT" here. + * Next, we added support for OEMx tables, signature "OEM". + * Valid tables were encountered with a null signature, so we've just + * given up on validating the signature, since it seems to be a waste + * of code. The original code was removed (05/2008). + */ + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + + /* Check if table is already registered */ + + for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { + if (!acpi_gbl_root_table_list.tables[i].pointer) { + status = + acpi_tb_verify_table(&acpi_gbl_root_table_list. + tables[i]); + if (ACPI_FAILURE(status) + || !acpi_gbl_root_table_list.tables[i].pointer) { + continue; + } + } + + /* + * Check for a table match on the entire table length, + * not just the header. + */ + if (table_desc->length != + acpi_gbl_root_table_list.tables[i].length) { + continue; + } + + if (ACPI_MEMCMP(table_desc->pointer, + acpi_gbl_root_table_list.tables[i].pointer, + acpi_gbl_root_table_list.tables[i].length)) { + continue; + } + + /* + * Note: the current mechanism does not unregister a table if it is + * dynamically unloaded. The related namespace entries are deleted, + * but the table remains in the root table list. + * + * The assumption here is that the number of different tables that + * will be loaded is actually small, and there is minimal overhead + * in just keeping the table in case it is needed again. + * + * If this assumption changes in the future (perhaps on large + * machines with many table load/unload operations), tables will + * need to be unregistered when they are unloaded, and slots in the + * root table list should be reused when empty. + */ + + /* + * Table is already registered. + * We can delete the table that was passed as a parameter. + */ + acpi_tb_delete_table(table_desc); + *table_index = i; + + if (acpi_gbl_root_table_list.tables[i]. + flags & ACPI_TABLE_IS_LOADED) { + + /* Table is still loaded, this is an error */ + + status = AE_ALREADY_EXISTS; + goto release; + } else { + /* Table was unloaded, allow it to be reloaded */ + + table_desc->pointer = + acpi_gbl_root_table_list.tables[i].pointer; + table_desc->address = + acpi_gbl_root_table_list.tables[i].address; + status = AE_OK; + goto print_header; + } + } + + /* Add the table to the global root table list */ + + status = acpi_tb_store_table(table_desc->address, table_desc->pointer, + table_desc->length, table_desc->flags, + table_index); + if (ACPI_FAILURE(status)) { + goto release; + } + + print_header: + acpi_tb_print_table_header(table_desc->address, table_desc->pointer); + + release: + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_resize_root_table_list + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Expand the size of global table array + * + ******************************************************************************/ + +acpi_status acpi_tb_resize_root_table_list(void) +{ + struct acpi_table_desc *tables; + + ACPI_FUNCTION_TRACE(tb_resize_root_table_list); + + /* allow_resize flag is a parameter to acpi_initialize_tables */ + + if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { + ACPI_ERROR((AE_INFO, + "Resize of Root Table Array is not allowed")); + return_ACPI_STATUS(AE_SUPPORT); + } + + /* Increase the Table Array size */ + + tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list. + size + ACPI_ROOT_TABLE_SIZE_INCREMENT) + * sizeof(struct acpi_table_desc)); + if (!tables) { + ACPI_ERROR((AE_INFO, + "Could not allocate new root table array")); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Copy and free the previous table array */ + + if (acpi_gbl_root_table_list.tables) { + ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, + (acpi_size) acpi_gbl_root_table_list.size * + sizeof(struct acpi_table_desc)); + + if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { + ACPI_FREE(acpi_gbl_root_table_list.tables); + } + } + + acpi_gbl_root_table_list.tables = tables; + acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT; + acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED; + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_store_table + * + * PARAMETERS: Address - Table address + * Table - Table header + * Length - Table length + * Flags - flags + * + * RETURN: Status and table index. + * + * DESCRIPTION: Add an ACPI table to the global table list + * + ******************************************************************************/ + +acpi_status +acpi_tb_store_table(acpi_physical_address address, + struct acpi_table_header *table, + u32 length, u8 flags, u32 *table_index) +{ + acpi_status status = AE_OK; + + /* Ensure that there is room for the table in the Root Table List */ + + if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) { + status = acpi_tb_resize_root_table_list(); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + /* Initialize added table */ + + acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. + address = address; + acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. + pointer = table; + acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length = + length; + acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. + owner_id = 0; + acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags = + flags; + + ACPI_MOVE_32_TO_32(& + (acpi_gbl_root_table_list. + tables[acpi_gbl_root_table_list.count].signature), + table->signature); + + *table_index = acpi_gbl_root_table_list.count; + acpi_gbl_root_table_list.count++; + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_delete_table + * + * PARAMETERS: table_index - Table index + * + * RETURN: None + * + * DESCRIPTION: Delete one internal ACPI table + * + ******************************************************************************/ + +void acpi_tb_delete_table(struct acpi_table_desc *table_desc) +{ + /* Table must be mapped or allocated */ + if (!table_desc->pointer) { + return; + } + switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_MAPPED: + acpi_os_unmap_memory(table_desc->pointer, table_desc->length); + break; + case ACPI_TABLE_ORIGIN_ALLOCATED: + ACPI_FREE(table_desc->pointer); + break; + default:; + } + + table_desc->pointer = NULL; +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_terminate + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Delete all internal ACPI tables + * + ******************************************************************************/ + +void acpi_tb_terminate(void) +{ + u32 i; + + ACPI_FUNCTION_TRACE(tb_terminate); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + + /* Delete the individual tables */ + + for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { + acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]); + } + + /* + * Delete the root table array if allocated locally. Array cannot be + * mapped, so we don't need to check for that flag. + */ + if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { + ACPI_FREE(acpi_gbl_root_table_list.tables); + } + + acpi_gbl_root_table_list.tables = NULL; + acpi_gbl_root_table_list.flags = 0; + acpi_gbl_root_table_list.count = 0; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_delete_namespace_by_owner + * + * PARAMETERS: table_index - Table index + * + * RETURN: None + * + * DESCRIPTION: Delete all namespace objects created when this table was loaded. + * + ******************************************************************************/ + +void acpi_tb_delete_namespace_by_owner(u32 table_index) +{ + acpi_owner_id owner_id; + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.count) { + owner_id = + acpi_gbl_root_table_list.tables[table_index].owner_id; + } else { + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + acpi_ns_delete_namespace_by_owner(owner_id); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_allocate_owner_id + * + * PARAMETERS: table_index - Table index + * + * RETURN: Status + * + * DESCRIPTION: Allocates owner_id in table_desc + * + ******************************************************************************/ + +acpi_status acpi_tb_allocate_owner_id(u32 table_index) +{ + acpi_status status = AE_BAD_PARAMETER; + + ACPI_FUNCTION_TRACE(tb_allocate_owner_id); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.count) { + status = acpi_ut_allocate_owner_id + (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_release_owner_id + * + * PARAMETERS: table_index - Table index + * + * RETURN: Status + * + * DESCRIPTION: Releases owner_id in table_desc + * + ******************************************************************************/ + +acpi_status acpi_tb_release_owner_id(u32 table_index) +{ + acpi_status status = AE_BAD_PARAMETER; + + ACPI_FUNCTION_TRACE(tb_release_owner_id); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.count) { + acpi_ut_release_owner_id(& + (acpi_gbl_root_table_list. + tables[table_index].owner_id)); + status = AE_OK; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_owner_id + * + * PARAMETERS: table_index - Table index + * owner_id - Where the table owner_id is returned + * + * RETURN: Status + * + * DESCRIPTION: returns owner_id for the ACPI table + * + ******************************************************************************/ + +acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id) +{ + acpi_status status = AE_BAD_PARAMETER; + + ACPI_FUNCTION_TRACE(tb_get_owner_id); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.count) { + *owner_id = + acpi_gbl_root_table_list.tables[table_index].owner_id; + status = AE_OK; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_is_table_loaded + * + * PARAMETERS: table_index - Table index + * + * RETURN: Table Loaded Flag + * + ******************************************************************************/ + +u8 acpi_tb_is_table_loaded(u32 table_index) +{ + u8 is_loaded = FALSE; + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.count) { + is_loaded = (u8) + (acpi_gbl_root_table_list.tables[table_index]. + flags & ACPI_TABLE_IS_LOADED); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return (is_loaded); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_set_table_loaded_flag + * + * PARAMETERS: table_index - Table index + * is_loaded - TRUE if table is loaded, FALSE otherwise + * + * RETURN: None + * + * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. + * + ******************************************************************************/ + +void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded) +{ + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.count) { + if (is_loaded) { + acpi_gbl_root_table_list.tables[table_index].flags |= + ACPI_TABLE_IS_LOADED; + } else { + acpi_gbl_root_table_list.tables[table_index].flags &= + ~ACPI_TABLE_IS_LOADED; + } + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); +} diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c new file mode 100644 index 000000000000..4eb7189974ca --- /dev/null +++ b/drivers/acpi/acpica/tbutils.c @@ -0,0 +1,582 @@ +/****************************************************************************** + * + * Module Name: tbutils - table utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbutils") + +/* Local prototypes */ +static acpi_physical_address +acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); + +/******************************************************************************* + * + * FUNCTION: acpi_tb_check_xsdt + * + * PARAMETERS: address - Pointer to the XSDT + * + * RETURN: status + * AE_OK - XSDT is okay + * AE_NO_MEMORY - can't map XSDT + * AE_INVALID_TABLE_LENGTH - invalid table length + * AE_NULL_ENTRY - XSDT has NULL entry + * + * DESCRIPTION: validate XSDT +******************************************************************************/ + +static acpi_status +acpi_tb_check_xsdt(acpi_physical_address address) +{ + struct acpi_table_header *table; + u32 length; + u64 xsdt_entry_address; + u8 *table_entry; + u32 table_count; + int i; + + table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); + if (!table) + return AE_NO_MEMORY; + + length = table->length; + acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + if (length < sizeof(struct acpi_table_header)) + return AE_INVALID_TABLE_LENGTH; + + table = acpi_os_map_memory(address, length); + if (!table) + return AE_NO_MEMORY; + + /* Calculate the number of tables described in XSDT */ + table_count = + (u32) ((table->length - + sizeof(struct acpi_table_header)) / sizeof(u64)); + table_entry = + ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); + for (i = 0; i < table_count; i++) { + ACPI_MOVE_64_TO_64(&xsdt_entry_address, table_entry); + if (!xsdt_entry_address) { + /* XSDT has NULL entry */ + break; + } + table_entry += sizeof(u64); + } + acpi_os_unmap_memory(table, length); + + if (i < table_count) + return AE_NULL_ENTRY; + else + return AE_OK; +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_initialize_facs + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global + * for accessing the Global Lock and Firmware Waking Vector + * + ******************************************************************************/ + +acpi_status acpi_tb_initialize_facs(void) +{ + acpi_status status; + + status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, + ACPI_CAST_INDIRECT_PTR(struct + acpi_table_header, + &acpi_gbl_FACS)); + return status; +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_tables_loaded + * + * PARAMETERS: None + * + * RETURN: TRUE if required ACPI tables are loaded + * + * DESCRIPTION: Determine if the minimum required ACPI tables are present + * (FADT, FACS, DSDT) + * + ******************************************************************************/ + +u8 acpi_tb_tables_loaded(void) +{ + + if (acpi_gbl_root_table_list.count >= 3) { + return (TRUE); + } + + return (FALSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_print_table_header + * + * PARAMETERS: Address - Table physical address + * Header - Table header + * + * RETURN: None + * + * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. + * + ******************************************************************************/ + +void +acpi_tb_print_table_header(acpi_physical_address address, + struct acpi_table_header *header) +{ + + if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { + + /* FACS only has signature and length fields of common table header */ + + ACPI_INFO((AE_INFO, "%4.4s %08lX, %04X", + header->signature, (unsigned long)address, + header->length)); + } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { + + /* RSDP has no common fields */ + + ACPI_INFO((AE_INFO, "RSDP %08lX, %04X (r%d %6.6s)", + (unsigned long)address, + (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> + revision > + 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, + header)->length : 20, + ACPI_CAST_PTR(struct acpi_table_rsdp, + header)->revision, + ACPI_CAST_PTR(struct acpi_table_rsdp, + header)->oem_id)); + } else { + /* Standard ACPI table with full common header */ + + ACPI_INFO((AE_INFO, + "%4.4s %08lX, %04X (r%d %6.6s %8.8s %8X %4.4s %8X)", + header->signature, (unsigned long)address, + header->length, header->revision, header->oem_id, + header->oem_table_id, header->oem_revision, + header->asl_compiler_id, + header->asl_compiler_revision)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_validate_checksum + * + * PARAMETERS: Table - ACPI table to verify + * Length - Length of entire table + * + * RETURN: Status + * + * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns + * exception on bad checksum. + * + ******************************************************************************/ + +acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) +{ + u8 checksum; + + /* Compute the checksum on the table */ + + checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); + + /* Checksum ok? (should be zero) */ + + if (checksum) { + ACPI_WARNING((AE_INFO, + "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", + table->signature, table->checksum, + (u8) (table->checksum - checksum))); + +#if (ACPI_CHECKSUM_ABORT) + + return (AE_BAD_CHECKSUM); +#endif + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_checksum + * + * PARAMETERS: Buffer - Pointer to memory region to be checked + * Length - Length of this memory region + * + * RETURN: Checksum (u8) + * + * DESCRIPTION: Calculates circular checksum of memory region. + * + ******************************************************************************/ + +u8 acpi_tb_checksum(u8 *buffer, u32 length) +{ + u8 sum = 0; + u8 *end = buffer + length; + + while (buffer < end) { + sum = (u8) (sum + *(buffer++)); + } + + return sum; +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_install_table + * + * PARAMETERS: Address - Physical address of DSDT or FACS + * Flags - Flags + * Signature - Table signature, NULL if no need to + * match + * table_index - Index into root table array + * + * RETURN: None + * + * DESCRIPTION: Install an ACPI table into the global data structure. + * + ******************************************************************************/ + +void +acpi_tb_install_table(acpi_physical_address address, + u8 flags, char *signature, u32 table_index) +{ + struct acpi_table_header *table; + + if (!address) { + ACPI_ERROR((AE_INFO, + "Null physical address for ACPI table [%s]", + signature)); + return; + } + + /* Map just the table header */ + + table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); + if (!table) { + return; + } + + /* If a particular signature is expected, signature must match */ + + if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { + ACPI_ERROR((AE_INFO, + "Invalid signature 0x%X for ACPI table [%s]", + *ACPI_CAST_PTR(u32, table->signature), signature)); + goto unmap_and_exit; + } + + /* Initialize the table entry */ + + acpi_gbl_root_table_list.tables[table_index].address = address; + acpi_gbl_root_table_list.tables[table_index].length = table->length; + acpi_gbl_root_table_list.tables[table_index].flags = flags; + + ACPI_MOVE_32_TO_32(& + (acpi_gbl_root_table_list.tables[table_index]. + signature), table->signature); + + acpi_tb_print_table_header(address, table); + + if (table_index == ACPI_TABLE_INDEX_DSDT) { + + /* Global integer width is based upon revision of the DSDT */ + + acpi_ut_set_integer_width(table->revision); + } + + unmap_and_exit: + acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_root_table_entry + * + * PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry + * table_entry_size - sizeof 32 or 64 (RSDT or XSDT) + * + * RETURN: Physical address extracted from the root table + * + * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on + * both 32-bit and 64-bit platforms + * + * NOTE: acpi_physical_address is 32-bit on 32-bit platforms, 64-bit on + * 64-bit platforms. + * + ******************************************************************************/ + +static acpi_physical_address +acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) +{ + u64 address64; + + /* + * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): + * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT + */ + if (table_entry_size == sizeof(u32)) { + /* + * 32-bit platform, RSDT: Return 32-bit table entry + * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return + */ + return ((acpi_physical_address) + (*ACPI_CAST_PTR(u32, table_entry))); + } else { + /* + * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return + * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit + */ + ACPI_MOVE_64_TO_64(&address64, table_entry); + +#if ACPI_MACHINE_WIDTH == 32 + if (address64 > ACPI_UINT32_MAX) { + + /* Will truncate 64-bit address to 32 bits, issue warning */ + + ACPI_WARNING((AE_INFO, + "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating", + ACPI_FORMAT_UINT64(address64))); + } +#endif + return ((acpi_physical_address) (address64)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_parse_root_table + * + * PARAMETERS: Rsdp - Pointer to the RSDP + * Flags - Flags + * + * RETURN: Status + * + * DESCRIPTION: This function is called to parse the Root System Description + * Table (RSDT or XSDT) + * + * NOTE: Tables are mapped (not copied) for efficiency. The FACS must + * be mapped and cannot be copied because it contains the actual + * memory location of the ACPI Global Lock. + * + ******************************************************************************/ + +acpi_status __init +acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) +{ + struct acpi_table_rsdp *rsdp; + u32 table_entry_size; + u32 i; + u32 table_count; + struct acpi_table_header *table; + acpi_physical_address address; + acpi_physical_address uninitialized_var(rsdt_address); + u32 length; + u8 *table_entry; + acpi_status status; + + ACPI_FUNCTION_TRACE(tb_parse_root_table); + + /* + * Map the entire RSDP and extract the address of the RSDT or XSDT + */ + rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp)); + if (!rsdp) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + acpi_tb_print_table_header(rsdp_address, + ACPI_CAST_PTR(struct acpi_table_header, + rsdp)); + + /* Differentiate between RSDT and XSDT root tables */ + + if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { + /* + * Root table is an XSDT (64-bit physical addresses). We must use the + * XSDT if the revision is > 1 and the XSDT pointer is present, as per + * the ACPI specification. + */ + address = (acpi_physical_address) rsdp->xsdt_physical_address; + table_entry_size = sizeof(u64); + rsdt_address = (acpi_physical_address) + rsdp->rsdt_physical_address; + } else { + /* Root table is an RSDT (32-bit physical addresses) */ + + address = (acpi_physical_address) rsdp->rsdt_physical_address; + table_entry_size = sizeof(u32); + } + + /* + * It is not possible to map more than one entry in some environments, + * so unmap the RSDP here before mapping other tables + */ + acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); + + if (table_entry_size == sizeof(u64)) { + if (acpi_tb_check_xsdt(address) == AE_NULL_ENTRY) { + /* XSDT has NULL entry, RSDT is used */ + address = rsdt_address; + table_entry_size = sizeof(u32); + ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry, " + "using RSDT")); + } + } + /* Map the RSDT/XSDT table header to get the full table length */ + + table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); + if (!table) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + acpi_tb_print_table_header(address, table); + + /* Get the length of the full table, verify length and map entire table */ + + length = table->length; + acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + + if (length < sizeof(struct acpi_table_header)) { + ACPI_ERROR((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", + length)); + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + table = acpi_os_map_memory(address, length); + if (!table) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Validate the root table checksum */ + + status = acpi_tb_verify_checksum(table, length); + if (ACPI_FAILURE(status)) { + acpi_os_unmap_memory(table, length); + return_ACPI_STATUS(status); + } + + /* Calculate the number of tables described in the root table */ + + table_count = + (u32) ((table->length - + sizeof(struct acpi_table_header)) / table_entry_size); + + /* + * First two entries in the table array are reserved for the DSDT and FACS, + * which are not actually present in the RSDT/XSDT - they come from the FADT + */ + table_entry = + ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); + acpi_gbl_root_table_list.count = 2; + + /* + * Initialize the root table array from the RSDT/XSDT + */ + for (i = 0; i < table_count; i++) { + if (acpi_gbl_root_table_list.count >= + acpi_gbl_root_table_list.size) { + + /* There is no more room in the root table array, attempt resize */ + + status = acpi_tb_resize_root_table_list(); + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, + "Truncating %u table entries!", + (unsigned) + (acpi_gbl_root_table_list.size - + acpi_gbl_root_table_list. + count))); + break; + } + } + + /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ + + acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. + address = + acpi_tb_get_root_table_entry(table_entry, table_entry_size); + + table_entry += table_entry_size; + acpi_gbl_root_table_list.count++; + } + + /* + * It is not possible to map more than one entry in some environments, + * so unmap the root table here before mapping other tables + */ + acpi_os_unmap_memory(table, length); + + /* + * Complete the initialization of the root table array by examining + * the header of each table + */ + for (i = 2; i < acpi_gbl_root_table_list.count; i++) { + acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. + address, flags, NULL, i); + + /* Special case for FADT - get the DSDT and FACS */ + + if (ACPI_COMPARE_NAME + (&acpi_gbl_root_table_list.tables[i].signature, + ACPI_SIG_FADT)) { + acpi_tb_parse_fadt(i, flags); + } + } + + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c new file mode 100644 index 000000000000..115796694a2f --- /dev/null +++ b/drivers/acpi/acpica/tbxface.c @@ -0,0 +1,735 @@ +/****************************************************************************** + * + * Module Name: tbxface - Public interfaces to the ACPI subsystem + * ACPI table oriented interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbxface") + +/* Local prototypes */ +static acpi_status acpi_tb_load_namespace(void); + +static int no_auto_ssdt; + +/******************************************************************************* + * + * FUNCTION: acpi_allocate_root_table + * + * PARAMETERS: initial_table_count - Size of initial_table_array, in number of + * struct acpi_table_desc structures + * + * RETURN: Status + * + * DESCRIPTION: Allocate a root table array. Used by i_aSL compiler and + * acpi_initialize_tables. + * + ******************************************************************************/ + +acpi_status acpi_allocate_root_table(u32 initial_table_count) +{ + + acpi_gbl_root_table_list.size = initial_table_count; + acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE; + + return (acpi_tb_resize_root_table_list()); +} + +/******************************************************************************* + * + * FUNCTION: acpi_initialize_tables + * + * PARAMETERS: initial_table_array - Pointer to an array of pre-allocated + * struct acpi_table_desc structures. If NULL, the + * array is dynamically allocated. + * initial_table_count - Size of initial_table_array, in number of + * struct acpi_table_desc structures + * allow_realloc - Flag to tell Table Manager if resize of + * pre-allocated array is allowed. Ignored + * if initial_table_array is NULL. + * + * RETURN: Status + * + * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT. + * + * NOTE: Allows static allocation of the initial table array in order + * to avoid the use of dynamic memory in confined environments + * such as the kernel boot sequence where it may not be available. + * + * If the host OS memory managers are initialized, use NULL for + * initial_table_array, and the table will be dynamically allocated. + * + ******************************************************************************/ + +acpi_status __init +acpi_initialize_tables(struct acpi_table_desc * initial_table_array, + u32 initial_table_count, u8 allow_resize) +{ + acpi_physical_address rsdp_address; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_initialize_tables); + + /* + * Set up the Root Table Array + * Allocate the table array if requested + */ + if (!initial_table_array) { + status = acpi_allocate_root_table(initial_table_count); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } else { + /* Root Table Array has been statically allocated by the host */ + + ACPI_MEMSET(initial_table_array, 0, + (acpi_size) initial_table_count * + sizeof(struct acpi_table_desc)); + + acpi_gbl_root_table_list.tables = initial_table_array; + acpi_gbl_root_table_list.size = initial_table_count; + acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN; + if (allow_resize) { + acpi_gbl_root_table_list.flags |= + ACPI_ROOT_ALLOW_RESIZE; + } + } + + /* Get the address of the RSDP */ + + rsdp_address = acpi_os_get_root_pointer(); + if (!rsdp_address) { + return_ACPI_STATUS(AE_NOT_FOUND); + } + + /* + * Get the root table (RSDT or XSDT) and extract all entries to the local + * Root Table Array. This array contains the information of the RSDT/XSDT + * in a common, more useable format. + */ + status = + acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_reallocate_root_table + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the + * root list from the previously provided scratch area. Should + * be called once dynamic memory allocation is available in the + * kernel + * + ******************************************************************************/ +acpi_status acpi_reallocate_root_table(void) +{ + struct acpi_table_desc *tables; + acpi_size new_size; + + ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); + + /* + * Only reallocate the root table if the host provided a static buffer + * for the table array in the call to acpi_initialize_tables. + */ + if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { + return_ACPI_STATUS(AE_SUPPORT); + } + + new_size = ((acpi_size) acpi_gbl_root_table_list.count + + ACPI_ROOT_TABLE_SIZE_INCREMENT) * + sizeof(struct acpi_table_desc); + + /* Create new array and copy the old array */ + + tables = ACPI_ALLOCATE_ZEROED(new_size); + if (!tables) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size); + + acpi_gbl_root_table_list.size = acpi_gbl_root_table_list.count; + acpi_gbl_root_table_list.tables = tables; + acpi_gbl_root_table_list.flags = + ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_load_table + * + * PARAMETERS: table_ptr - pointer to a buffer containing the entire + * table to be loaded + * + * RETURN: Status + * + * DESCRIPTION: This function is called to load a table from the caller's + * buffer. The buffer must contain an entire ACPI Table including + * a valid header. The header fields will be verified, and if it + * is determined that the table is invalid, the call will fail. + * + ******************************************************************************/ +acpi_status acpi_load_table(struct acpi_table_header *table_ptr) +{ + acpi_status status; + u32 table_index; + struct acpi_table_desc table_desc; + + if (!table_ptr) + return AE_BAD_PARAMETER; + + ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); + table_desc.pointer = table_ptr; + table_desc.length = table_ptr->length; + table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN; + + /* + * Install the new table into the local data structures + */ + status = acpi_tb_add_table(&table_desc, &table_index); + if (ACPI_FAILURE(status)) { + return status; + } + status = acpi_ns_load_table(table_index, acpi_gbl_root_node); + return status; +} + +ACPI_EXPORT_SYMBOL(acpi_load_table) + +/****************************************************************************** + * + * FUNCTION: acpi_get_table_header + * + * PARAMETERS: Signature - ACPI signature of needed table + * Instance - Which instance (for SSDTs) + * out_table_header - The pointer to the table header to fill + * + * RETURN: Status and pointer to mapped table header + * + * DESCRIPTION: Finds an ACPI table header. + * + * NOTE: Caller is responsible in unmapping the header with + * acpi_os_unmap_memory + * + *****************************************************************************/ +acpi_status +acpi_get_table_header(char *signature, + u32 instance, struct acpi_table_header *out_table_header) +{ + u32 i; + u32 j; + struct acpi_table_header *header; + + /* Parameter validation */ + + if (!signature || !out_table_header) { + return (AE_BAD_PARAMETER); + } + + /* + * Walk the root table list + */ + for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { + if (!ACPI_COMPARE_NAME + (&(acpi_gbl_root_table_list.tables[i].signature), + signature)) { + continue; + } + + if (++j < instance) { + continue; + } + + if (!acpi_gbl_root_table_list.tables[i].pointer) { + if ((acpi_gbl_root_table_list.tables[i]. + flags & ACPI_TABLE_ORIGIN_MASK) == + ACPI_TABLE_ORIGIN_MAPPED) { + header = + acpi_os_map_memory(acpi_gbl_root_table_list. + tables[i].address, + sizeof(struct + acpi_table_header)); + if (!header) { + return AE_NO_MEMORY; + } + ACPI_MEMCPY(out_table_header, header, + sizeof(struct acpi_table_header)); + acpi_os_unmap_memory(header, + sizeof(struct + acpi_table_header)); + } else { + return AE_NOT_FOUND; + } + } else { + ACPI_MEMCPY(out_table_header, + acpi_gbl_root_table_list.tables[i].pointer, + sizeof(struct acpi_table_header)); + } + return (AE_OK); + } + + return (AE_NOT_FOUND); +} + +ACPI_EXPORT_SYMBOL(acpi_get_table_header) + +/****************************************************************************** + * + * FUNCTION: acpi_unload_table_id + * + * PARAMETERS: id - Owner ID of the table to be removed. + * + * RETURN: Status + * + * DESCRIPTION: This routine is used to force the unload of a table (by id) + * + ******************************************************************************/ +acpi_status acpi_unload_table_id(acpi_owner_id id) +{ + int i; + acpi_status status = AE_NOT_EXIST; + + ACPI_FUNCTION_TRACE(acpi_unload_table_id); + + /* Find table in the global table list */ + for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { + if (id != acpi_gbl_root_table_list.tables[i].owner_id) { + continue; + } + /* + * Delete all namespace objects owned by this table. Note that these + * objects can appear anywhere in the namespace by virtue of the AML + * "Scope" operator. Thus, we need to track ownership by an ID, not + * simply a position within the hierarchy + */ + acpi_tb_delete_namespace_by_owner(i); + status = acpi_tb_release_owner_id(i); + acpi_tb_set_table_loaded_flag(i, FALSE); + break; + } + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_unload_table_id) + +/******************************************************************************* + * + * FUNCTION: acpi_get_table + * + * PARAMETERS: Signature - ACPI signature of needed table + * Instance - Which instance (for SSDTs) + * out_table - Where the pointer to the table is returned + * + * RETURN: Status and pointer to table + * + * DESCRIPTION: Finds and verifies an ACPI table. + * + *****************************************************************************/ +acpi_status +acpi_get_table(char *signature, + u32 instance, struct acpi_table_header **out_table) +{ + u32 i; + u32 j; + acpi_status status; + + /* Parameter validation */ + + if (!signature || !out_table) { + return (AE_BAD_PARAMETER); + } + + /* + * Walk the root table list + */ + for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { + if (!ACPI_COMPARE_NAME + (&(acpi_gbl_root_table_list.tables[i].signature), + signature)) { + continue; + } + + if (++j < instance) { + continue; + } + + status = + acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]); + if (ACPI_SUCCESS(status)) { + *out_table = acpi_gbl_root_table_list.tables[i].pointer; + } + + if (!acpi_gbl_permanent_mmap) { + acpi_gbl_root_table_list.tables[i].pointer = NULL; + } + + return (status); + } + + return (AE_NOT_FOUND); +} + +ACPI_EXPORT_SYMBOL(acpi_get_table) + +/******************************************************************************* + * + * FUNCTION: acpi_get_table_by_index + * + * PARAMETERS: table_index - Table index + * Table - Where the pointer to the table is returned + * + * RETURN: Status and pointer to the table + * + * DESCRIPTION: Obtain a table by an index into the global table list. + * + ******************************************************************************/ +acpi_status +acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_get_table_by_index); + + /* Parameter validation */ + + if (!table) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + + /* Validate index */ + + if (table_index >= acpi_gbl_root_table_list.count) { + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (!acpi_gbl_root_table_list.tables[table_index].pointer) { + + /* Table is not mapped, map it */ + + status = + acpi_tb_verify_table(&acpi_gbl_root_table_list. + tables[table_index]); + if (ACPI_FAILURE(status)) { + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); + } + } + + *table = acpi_gbl_root_table_list.tables[table_index].pointer; + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) + +/******************************************************************************* + * + * FUNCTION: acpi_tb_load_namespace + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in + * the RSDT/XSDT. + * + ******************************************************************************/ +static acpi_status acpi_tb_load_namespace(void) +{ + acpi_status status; + struct acpi_table_header *table; + u32 i; + + ACPI_FUNCTION_TRACE(tb_load_namespace); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + + /* + * Load the namespace. The DSDT is required, but any SSDT and PSDT tables + * are optional. + */ + if (!acpi_gbl_root_table_list.count || + !ACPI_COMPARE_NAME(& + (acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT].signature), + ACPI_SIG_DSDT) + || + ACPI_FAILURE(acpi_tb_verify_table + (&acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT]))) { + status = AE_NO_ACPI_TABLES; + goto unlock_and_exit; + } + + /* + * Find DSDT table + */ + status = + acpi_os_table_override(acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT].pointer, + &table); + if (ACPI_SUCCESS(status) && table) { + /* + * DSDT table has been found + */ + acpi_tb_delete_table(&acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT]); + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer = + table; + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = + table->length; + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = + ACPI_TABLE_ORIGIN_UNKNOWN; + + ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); + acpi_tb_print_table_header(0, table); + + if (no_auto_ssdt == 0) { + printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n"); + } + } + + status = + acpi_tb_verify_table(&acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT]); + if (ACPI_FAILURE(status)) { + + /* A valid DSDT is required */ + + status = AE_NO_ACPI_TABLES; + goto unlock_and_exit; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + + /* + * Load and parse tables. + */ + status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Load any SSDT or PSDT tables. Note: Loop leaves tables locked + */ + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { + if ((!ACPI_COMPARE_NAME + (&(acpi_gbl_root_table_list.tables[i].signature), + ACPI_SIG_SSDT) + && + !ACPI_COMPARE_NAME(& + (acpi_gbl_root_table_list.tables[i]. + signature), ACPI_SIG_PSDT)) + || + ACPI_FAILURE(acpi_tb_verify_table + (&acpi_gbl_root_table_list.tables[i]))) { + continue; + } + + if (no_auto_ssdt) { + printk(KERN_WARNING "ACPI: SSDT ignored due to \"acpi_no_auto_ssdt\"\n"); + continue; + } + + /* Ignore errors while loading tables, get as many as possible */ + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + (void)acpi_ns_load_table(i, acpi_gbl_root_node); + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_load_tables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT + * + ******************************************************************************/ + +acpi_status acpi_load_tables(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_load_tables); + + /* + * Load the namespace from the tables + */ + status = acpi_tb_load_namespace(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "While loading namespace from ACPI tables")); + } + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_load_tables) + + +/******************************************************************************* + * + * FUNCTION: acpi_install_table_handler + * + * PARAMETERS: Handler - Table event handler + * Context - Value passed to the handler on each event + * + * RETURN: Status + * + * DESCRIPTION: Install table event handler + * + ******************************************************************************/ +acpi_status +acpi_install_table_handler(acpi_tbl_handler handler, void *context) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_table_handler); + + if (!handler) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Don't allow more than one handler */ + + if (acpi_gbl_table_handler) { + status = AE_ALREADY_EXISTS; + goto cleanup; + } + + /* Install the handler */ + + acpi_gbl_table_handler = handler; + acpi_gbl_table_handler_context = context; + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_table_handler) + +/******************************************************************************* + * + * FUNCTION: acpi_remove_table_handler + * + * PARAMETERS: Handler - Table event handler that was installed + * previously. + * + * RETURN: Status + * + * DESCRIPTION: Remove table event handler + * + ******************************************************************************/ +acpi_status acpi_remove_table_handler(acpi_tbl_handler handler) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_remove_table_handler); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Make sure that the installed handler is the same */ + + if (!handler || handler != acpi_gbl_table_handler) { + status = AE_BAD_PARAMETER; + goto cleanup; + } + + /* Remove the handler */ + + acpi_gbl_table_handler = NULL; + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_remove_table_handler) + + +static int __init acpi_no_auto_ssdt_setup(char *s) { + + printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); + + no_auto_ssdt = 1; + + return 1; +} + +__setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup); diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c new file mode 100644 index 000000000000..3495dca4e86b --- /dev/null +++ b/drivers/acpi/acpica/tbxfroot.c @@ -0,0 +1,274 @@ +/****************************************************************************** + * + * Module Name: tbxfroot - Find the root ACPI table (RSDT) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbxfroot") + +/* Local prototypes */ +static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); + +static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp); + +/******************************************************************************* + * + * FUNCTION: acpi_tb_validate_rsdp + * + * PARAMETERS: Rsdp - Pointer to unvalidated RSDP + * + * RETURN: Status + * + * DESCRIPTION: Validate the RSDP (ptr) + * + ******************************************************************************/ + +static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) +{ + ACPI_FUNCTION_ENTRY(); + + /* + * The signature and checksum must both be correct + * + * Note: Sometimes there exists more than one RSDP in memory; the valid + * RSDP has a valid checksum, all others have an invalid checksum. + */ + if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1) + != 0) { + + /* Nope, BAD Signature */ + + return (AE_BAD_SIGNATURE); + } + + /* Check the standard checksum */ + + if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { + return (AE_BAD_CHECKSUM); + } + + /* Check extended checksum if table version >= 2 */ + + if ((rsdp->revision >= 2) && + (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { + return (AE_BAD_CHECKSUM); + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_find_root_pointer + * + * PARAMETERS: table_address - Where the table pointer is returned + * + * RETURN: Status, RSDP physical address + * + * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor + * pointer structure. If it is found, set *RSDP to point to it. + * + * NOTE1: The RSDP must be either in the first 1_k of the Extended + * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) + * Only a 32-bit physical address is necessary. + * + * NOTE2: This function is always available, regardless of the + * initialization state of the rest of ACPI. + * + ******************************************************************************/ + +acpi_status acpi_find_root_pointer(acpi_size *table_address) +{ + u8 *table_ptr; + u8 *mem_rover; + u32 physical_address; + + ACPI_FUNCTION_TRACE(acpi_find_root_pointer); + + /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ + + table_ptr = acpi_os_map_memory((acpi_physical_address) + ACPI_EBDA_PTR_LOCATION, + ACPI_EBDA_PTR_LENGTH); + if (!table_ptr) { + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X for length %X", + ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); + + return_ACPI_STATUS(AE_NO_MEMORY); + } + + ACPI_MOVE_16_TO_32(&physical_address, table_ptr); + + /* Convert segment part to physical address */ + + physical_address <<= 4; + acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH); + + /* EBDA present? */ + + if (physical_address > 0x400) { + /* + * 1b) Search EBDA paragraphs (EBDA is required to be a + * minimum of 1_k length) + */ + table_ptr = acpi_os_map_memory((acpi_physical_address) + physical_address, + ACPI_EBDA_WINDOW_SIZE); + if (!table_ptr) { + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X for length %X", + physical_address, ACPI_EBDA_WINDOW_SIZE)); + + return_ACPI_STATUS(AE_NO_MEMORY); + } + + mem_rover = + acpi_tb_scan_memory_for_rsdp(table_ptr, + ACPI_EBDA_WINDOW_SIZE); + acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); + + if (mem_rover) { + + /* Return the physical address */ + + physical_address += + (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); + + *table_address = physical_address; + return_ACPI_STATUS(AE_OK); + } + } + + /* + * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh + */ + table_ptr = acpi_os_map_memory((acpi_physical_address) + ACPI_HI_RSDP_WINDOW_BASE, + ACPI_HI_RSDP_WINDOW_SIZE); + + if (!table_ptr) { + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X for length %X", + ACPI_HI_RSDP_WINDOW_BASE, + ACPI_HI_RSDP_WINDOW_SIZE)); + + return_ACPI_STATUS(AE_NO_MEMORY); + } + + mem_rover = + acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); + acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); + + if (mem_rover) { + + /* Return the physical address */ + + physical_address = (u32) + (ACPI_HI_RSDP_WINDOW_BASE + + ACPI_PTR_DIFF(mem_rover, table_ptr)); + + *table_address = physical_address; + return_ACPI_STATUS(AE_OK); + } + + /* A valid RSDP was not found */ + + ACPI_ERROR((AE_INFO, "A valid RSDP was not found")); + return_ACPI_STATUS(AE_NOT_FOUND); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_scan_memory_for_rsdp + * + * PARAMETERS: start_address - Starting pointer for search + * Length - Maximum length to search + * + * RETURN: Pointer to the RSDP if found, otherwise NULL. + * + * DESCRIPTION: Search a block of memory for the RSDP signature + * + ******************************************************************************/ +static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) +{ + acpi_status status; + u8 *mem_rover; + u8 *end_address; + + ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp); + + end_address = start_address + length; + + /* Search from given start address for the requested length */ + + for (mem_rover = start_address; mem_rover < end_address; + mem_rover += ACPI_RSDP_SCAN_STEP) { + + /* The RSDP signature and checksum must both be correct */ + + status = + acpi_tb_validate_rsdp(ACPI_CAST_PTR + (struct acpi_table_rsdp, mem_rover)); + if (ACPI_SUCCESS(status)) { + + /* Sig and checksum valid, we have found a real RSDP */ + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "RSDP located at physical address %p\n", + mem_rover)); + return_PTR(mem_rover); + } + + /* No sig match or bad checksum, keep searching */ + } + + /* Searched entire block, no RSDP was found */ + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Searched entire block from %p, valid RSDP was not found\n", + start_address)); + return_PTR(NULL); +} diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c new file mode 100644 index 000000000000..2a017b29aa41 --- /dev/null +++ b/drivers/acpi/acpica/utalloc.c @@ -0,0 +1,383 @@ +/****************************************************************************** + * + * Module Name: utalloc - local memory allocation routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utalloc") + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_caches + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create all local caches + * + ******************************************************************************/ +acpi_status acpi_ut_create_caches(void) +{ + acpi_status status; + + /* Object Caches, for frequently used objects */ + + status = + acpi_os_create_cache("Acpi-Namespace", + sizeof(struct acpi_namespace_node), + ACPI_MAX_NAMESPACE_CACHE_DEPTH, + &acpi_gbl_namespace_cache); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = + acpi_os_create_cache("Acpi-State", sizeof(union acpi_generic_state), + ACPI_MAX_STATE_CACHE_DEPTH, + &acpi_gbl_state_cache); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = + acpi_os_create_cache("Acpi-Parse", + sizeof(struct acpi_parse_obj_common), + ACPI_MAX_PARSE_CACHE_DEPTH, + &acpi_gbl_ps_node_cache); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = + acpi_os_create_cache("Acpi-ParseExt", + sizeof(struct acpi_parse_obj_named), + ACPI_MAX_EXTPARSE_CACHE_DEPTH, + &acpi_gbl_ps_node_ext_cache); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = + acpi_os_create_cache("Acpi-Operand", + sizeof(union acpi_operand_object), + ACPI_MAX_OBJECT_CACHE_DEPTH, + &acpi_gbl_operand_cache); + if (ACPI_FAILURE(status)) { + return (status); + } +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + /* Memory allocation lists */ + + status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = + acpi_ut_create_list("Acpi-Namespace", + sizeof(struct acpi_namespace_node), + &acpi_gbl_ns_node_list); + if (ACPI_FAILURE(status)) { + return (status); + } +#endif + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_delete_caches + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Purge and delete all local caches + * + ******************************************************************************/ + +acpi_status acpi_ut_delete_caches(void) +{ +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + char buffer[7]; + + if (acpi_gbl_display_final_mem_stats) { + ACPI_STRCPY(buffer, "MEMORY"); + (void)acpi_db_display_statistics(buffer); + } +#endif + + (void)acpi_os_delete_cache(acpi_gbl_namespace_cache); + acpi_gbl_namespace_cache = NULL; + + (void)acpi_os_delete_cache(acpi_gbl_state_cache); + acpi_gbl_state_cache = NULL; + + (void)acpi_os_delete_cache(acpi_gbl_operand_cache); + acpi_gbl_operand_cache = NULL; + + (void)acpi_os_delete_cache(acpi_gbl_ps_node_cache); + acpi_gbl_ps_node_cache = NULL; + + (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache); + acpi_gbl_ps_node_ext_cache = NULL; + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + /* Debug only - display leftover memory allocation, if any */ + + acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL); + + /* Free memory lists */ + + ACPI_FREE(acpi_gbl_global_list); + acpi_gbl_global_list = NULL; + + ACPI_FREE(acpi_gbl_ns_node_list); + acpi_gbl_ns_node_list = NULL; +#endif + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_validate_buffer + * + * PARAMETERS: Buffer - Buffer descriptor to be validated + * + * RETURN: Status + * + * DESCRIPTION: Perform parameter validation checks on an struct acpi_buffer + * + ******************************************************************************/ + +acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer) +{ + + /* Obviously, the structure pointer must be valid */ + + if (!buffer) { + return (AE_BAD_PARAMETER); + } + + /* Special semantics for the length */ + + if ((buffer->length == ACPI_NO_BUFFER) || + (buffer->length == ACPI_ALLOCATE_BUFFER) || + (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) { + return (AE_OK); + } + + /* Length is valid, the buffer pointer must be also */ + + if (!buffer->pointer) { + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_initialize_buffer + * + * PARAMETERS: Buffer - Buffer to be validated + * required_length - Length needed + * + * RETURN: Status + * + * DESCRIPTION: Validate that the buffer is of the required length or + * allocate a new buffer. Returned buffer is always zeroed. + * + ******************************************************************************/ + +acpi_status +acpi_ut_initialize_buffer(struct acpi_buffer * buffer, + acpi_size required_length) +{ + acpi_size input_buffer_length; + + /* Parameter validation */ + + if (!buffer || !required_length) { + return (AE_BAD_PARAMETER); + } + + /* + * Buffer->Length is used as both an input and output parameter. Get the + * input actual length and set the output required buffer length. + */ + input_buffer_length = buffer->length; + buffer->length = required_length; + + /* + * The input buffer length contains the actual buffer length, or the type + * of buffer to be allocated by this routine. + */ + switch (input_buffer_length) { + case ACPI_NO_BUFFER: + + /* Return the exception (and the required buffer length) */ + + return (AE_BUFFER_OVERFLOW); + + case ACPI_ALLOCATE_BUFFER: + + /* Allocate a new buffer */ + + buffer->pointer = acpi_os_allocate(required_length); + break; + + case ACPI_ALLOCATE_LOCAL_BUFFER: + + /* Allocate a new buffer with local interface to allow tracking */ + + buffer->pointer = ACPI_ALLOCATE(required_length); + break; + + default: + + /* Existing buffer: Validate the size of the buffer */ + + if (input_buffer_length < required_length) { + return (AE_BUFFER_OVERFLOW); + } + break; + } + + /* Validate allocation from above or input buffer pointer */ + + if (!buffer->pointer) { + return (AE_NO_MEMORY); + } + + /* Have a valid buffer, clear it */ + + ACPI_MEMSET(buffer->pointer, 0, required_length); + return (AE_OK); +} + +#ifdef NOT_USED_BY_LINUX +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of malloc. + * + ******************************************************************************/ + +void *acpi_ut_allocate(acpi_size size, + u32 component, const char *module, u32 line) +{ + void *allocation; + + ACPI_FUNCTION_TRACE_U32(ut_allocate, size); + + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + ACPI_WARNING((module, line, + "Attempt to allocate zero bytes, allocating 1 byte")); + size = 1; + } + + allocation = acpi_os_allocate(size); + if (!allocation) { + + /* Report allocation error */ + + ACPI_WARNING((module, line, + "Could not allocate size %X", (u32) size)); + + return_PTR(NULL); + } + + return_PTR(allocation); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate_zeroed + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. + * + ******************************************************************************/ + +void *acpi_ut_allocate_zeroed(acpi_size size, + u32 component, const char *module, u32 line) +{ + void *allocation; + + ACPI_FUNCTION_ENTRY(); + + allocation = acpi_ut_allocate(size, component, module, line); + if (allocation) { + + /* Clear the memory block */ + + ACPI_MEMSET(allocation, 0, size); + } + + return (allocation); +} +#endif diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c new file mode 100644 index 000000000000..e6f3002312e5 --- /dev/null +++ b/drivers/acpi/acpica/utcopy.c @@ -0,0 +1,970 @@ +/****************************************************************************** + * + * Module Name: utcopy - Internal to external object translation utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utcopy") + +/* Local prototypes */ +static acpi_status +acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, + union acpi_object *external_object, + u8 * data_space, acpi_size * buffer_space_used); + +static acpi_status +acpi_ut_copy_ielement_to_ielement(u8 object_type, + union acpi_operand_object *source_object, + union acpi_generic_state *state, + void *context); + +static acpi_status +acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object, + u8 * buffer, acpi_size * space_used); + +static acpi_status +acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj, + union acpi_operand_object **return_obj); + +static acpi_status +acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, + union acpi_operand_object **internal_object); + +static acpi_status +acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, + union acpi_operand_object *dest_desc); + +static acpi_status +acpi_ut_copy_ielement_to_eelement(u8 object_type, + union acpi_operand_object *source_object, + union acpi_generic_state *state, + void *context); + +static acpi_status +acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, + union acpi_operand_object *dest_obj, + struct acpi_walk_state *walk_state); + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_isimple_to_esimple + * + * PARAMETERS: internal_object - Source object to be copied + * external_object - Where to return the copied object + * data_space - Where object data is returned (such as + * buffer and string data) + * buffer_space_used - Length of data_space that was used + * + * RETURN: Status + * + * DESCRIPTION: This function is called to copy a simple internal object to + * an external object. + * + * The data_space buffer is assumed to have sufficient space for + * the object. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, + union acpi_object *external_object, + u8 * data_space, acpi_size * buffer_space_used) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple); + + *buffer_space_used = 0; + + /* + * Check for NULL object case (could be an uninitialized + * package element) + */ + if (!internal_object) { + return_ACPI_STATUS(AE_OK); + } + + /* Always clear the external object */ + + ACPI_MEMSET(external_object, 0, sizeof(union acpi_object)); + + /* + * In general, the external object will be the same type as + * the internal object + */ + external_object->type = ACPI_GET_OBJECT_TYPE(internal_object); + + /* However, only a limited number of external types are supported */ + + switch (ACPI_GET_OBJECT_TYPE(internal_object)) { + case ACPI_TYPE_STRING: + + external_object->string.pointer = (char *)data_space; + external_object->string.length = internal_object->string.length; + *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size) + internal_object-> + string. + length + 1); + + ACPI_MEMCPY((void *)data_space, + (void *)internal_object->string.pointer, + (acpi_size) internal_object->string.length + 1); + break; + + case ACPI_TYPE_BUFFER: + + external_object->buffer.pointer = data_space; + external_object->buffer.length = internal_object->buffer.length; + *buffer_space_used = + ACPI_ROUND_UP_TO_NATIVE_WORD(internal_object->string. + length); + + ACPI_MEMCPY((void *)data_space, + (void *)internal_object->buffer.pointer, + internal_object->buffer.length); + break; + + case ACPI_TYPE_INTEGER: + + external_object->integer.value = internal_object->integer.value; + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + /* This is an object reference. */ + + switch (internal_object->reference.class) { + case ACPI_REFCLASS_NAME: + + /* + * For namepath, return the object handle ("reference") + * We are referring to the namespace node + */ + external_object->reference.handle = + internal_object->reference.node; + external_object->reference.actual_type = + acpi_ns_get_type(internal_object->reference.node); + break; + + default: + + /* All other reference types are unsupported */ + + return_ACPI_STATUS(AE_TYPE); + } + break; + + case ACPI_TYPE_PROCESSOR: + + external_object->processor.proc_id = + internal_object->processor.proc_id; + external_object->processor.pblk_address = + internal_object->processor.address; + external_object->processor.pblk_length = + internal_object->processor.length; + break; + + case ACPI_TYPE_POWER: + + external_object->power_resource.system_level = + internal_object->power_resource.system_level; + + external_object->power_resource.resource_order = + internal_object->power_resource.resource_order; + break; + + default: + /* + * There is no corresponding external object type + */ + ACPI_ERROR((AE_INFO, + "Unsupported object type, cannot convert to external object: %s", + acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE + (internal_object)))); + + return_ACPI_STATUS(AE_SUPPORT); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_ielement_to_eelement + * + * PARAMETERS: acpi_pkg_callback + * + * RETURN: Status + * + * DESCRIPTION: Copy one package element to another package element + * + ******************************************************************************/ + +static acpi_status +acpi_ut_copy_ielement_to_eelement(u8 object_type, + union acpi_operand_object *source_object, + union acpi_generic_state *state, + void *context) +{ + acpi_status status = AE_OK; + struct acpi_pkg_info *info = (struct acpi_pkg_info *)context; + acpi_size object_space; + u32 this_index; + union acpi_object *target_object; + + ACPI_FUNCTION_ENTRY(); + + this_index = state->pkg.index; + target_object = (union acpi_object *) + &((union acpi_object *)(state->pkg.dest_object))->package. + elements[this_index]; + + switch (object_type) { + case ACPI_COPY_TYPE_SIMPLE: + + /* + * This is a simple or null object + */ + status = acpi_ut_copy_isimple_to_esimple(source_object, + target_object, + info->free_space, + &object_space); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_COPY_TYPE_PACKAGE: + + /* + * Build the package object + */ + target_object->type = ACPI_TYPE_PACKAGE; + target_object->package.count = source_object->package.count; + target_object->package.elements = + ACPI_CAST_PTR(union acpi_object, info->free_space); + + /* + * Pass the new package object back to the package walk routine + */ + state->pkg.this_target_obj = target_object; + + /* + * Save space for the array of objects (Package elements) + * update the buffer length counter + */ + object_space = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size) + target_object-> + package.count * + sizeof(union + acpi_object)); + break; + + default: + return (AE_BAD_PARAMETER); + } + + info->free_space += object_space; + info->length += object_space; + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_ipackage_to_epackage + * + * PARAMETERS: internal_object - Pointer to the object we are returning + * Buffer - Where the object is returned + * space_used - Where the object length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to place a package object in a user + * buffer. A package object by definition contains other objects. + * + * The buffer is assumed to have sufficient space for the object. + * The caller must have verified the buffer length needed using the + * acpi_ut_get_object_size function before calling this function. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object, + u8 * buffer, acpi_size * space_used) +{ + union acpi_object *external_object; + acpi_status status; + struct acpi_pkg_info info; + + ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage); + + /* + * First package at head of the buffer + */ + external_object = ACPI_CAST_PTR(union acpi_object, buffer); + + /* + * Free space begins right after the first package + */ + info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); + info.free_space = + buffer + ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); + info.object_space = 0; + info.num_packages = 1; + + external_object->type = ACPI_GET_OBJECT_TYPE(internal_object); + external_object->package.count = internal_object->package.count; + external_object->package.elements = ACPI_CAST_PTR(union acpi_object, + info.free_space); + + /* + * Leave room for an array of ACPI_OBJECTS in the buffer + * and move the free space past it + */ + info.length += (acpi_size) external_object->package.count * + ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); + info.free_space += external_object->package.count * + ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); + + status = acpi_ut_walk_package_tree(internal_object, external_object, + acpi_ut_copy_ielement_to_eelement, + &info); + + *space_used = info.length; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_iobject_to_eobject + * + * PARAMETERS: internal_object - The internal object to be converted + * buffer_ptr - Where the object is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to build an API object to be returned to + * the caller. + * + ******************************************************************************/ + +acpi_status +acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object, + struct acpi_buffer *ret_buffer) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject); + + if (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE) { + /* + * Package object: Copy all subobjects (including + * nested packages) + */ + status = acpi_ut_copy_ipackage_to_epackage(internal_object, + ret_buffer->pointer, + &ret_buffer->length); + } else { + /* + * Build a simple object (no nested objects) + */ + status = acpi_ut_copy_isimple_to_esimple(internal_object, + ACPI_CAST_PTR(union + acpi_object, + ret_buffer-> + pointer), + ACPI_ADD_PTR(u8, + ret_buffer-> + pointer, + ACPI_ROUND_UP_TO_NATIVE_WORD + (sizeof + (union + acpi_object))), + &ret_buffer->length); + /* + * build simple does not include the object size in the length + * so we add it in here + */ + ret_buffer->length += sizeof(union acpi_object); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_esimple_to_isimple + * + * PARAMETERS: external_object - The external object to be converted + * ret_internal_object - Where the internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: This function copies an external object to an internal one. + * NOTE: Pointers can be copied, we don't need to copy data. + * (The pointers have to be valid in our address space no matter + * what we do with them!) + * + ******************************************************************************/ + +static acpi_status +acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, + union acpi_operand_object **ret_internal_object) +{ + union acpi_operand_object *internal_object; + + ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple); + + /* + * Simple types supported are: String, Buffer, Integer + */ + switch (external_object->type) { + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_LOCAL_REFERENCE: + + internal_object = acpi_ut_create_internal_object((u8) + external_object-> + type); + if (!internal_object) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + break; + + case ACPI_TYPE_ANY: /* This is the case for a NULL object */ + + *ret_internal_object = NULL; + return_ACPI_STATUS(AE_OK); + + default: + /* All other types are not supported */ + + ACPI_ERROR((AE_INFO, + "Unsupported object type, cannot convert to internal object: %s", + acpi_ut_get_type_name(external_object->type))); + + return_ACPI_STATUS(AE_SUPPORT); + } + + /* Must COPY string and buffer contents */ + + switch (external_object->type) { + case ACPI_TYPE_STRING: + + internal_object->string.pointer = + ACPI_ALLOCATE_ZEROED((acpi_size) external_object->string. + length + 1); + if (!internal_object->string.pointer) { + goto error_exit; + } + + ACPI_MEMCPY(internal_object->string.pointer, + external_object->string.pointer, + external_object->string.length); + + internal_object->string.length = external_object->string.length; + break; + + case ACPI_TYPE_BUFFER: + + internal_object->buffer.pointer = + ACPI_ALLOCATE_ZEROED(external_object->buffer.length); + if (!internal_object->buffer.pointer) { + goto error_exit; + } + + ACPI_MEMCPY(internal_object->buffer.pointer, + external_object->buffer.pointer, + external_object->buffer.length); + + internal_object->buffer.length = external_object->buffer.length; + + /* Mark buffer data valid */ + + internal_object->buffer.flags |= AOPOBJ_DATA_VALID; + break; + + case ACPI_TYPE_INTEGER: + + internal_object->integer.value = external_object->integer.value; + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + /* TBD: should validate incoming handle */ + + internal_object->reference.class = ACPI_REFCLASS_NAME; + internal_object->reference.node = + external_object->reference.handle; + break; + + default: + /* Other types can't get here */ + break; + } + + *ret_internal_object = internal_object; + return_ACPI_STATUS(AE_OK); + + error_exit: + acpi_ut_remove_reference(internal_object); + return_ACPI_STATUS(AE_NO_MEMORY); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_epackage_to_ipackage + * + * PARAMETERS: external_object - The external object to be converted + * internal_object - Where the internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Copy an external package object to an internal package. + * Handles nested packages. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, + union acpi_operand_object **internal_object) +{ + acpi_status status = AE_OK; + union acpi_operand_object *package_object; + union acpi_operand_object **package_elements; + u32 i; + + ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage); + + /* Create the package object */ + + package_object = + acpi_ut_create_package_object(external_object->package.count); + if (!package_object) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + package_elements = package_object->package.elements; + + /* + * Recursive implementation. Probably ok, since nested external packages + * as parameters should be very rare. + */ + for (i = 0; i < external_object->package.count; i++) { + status = + acpi_ut_copy_eobject_to_iobject(&external_object->package. + elements[i], + &package_elements[i]); + if (ACPI_FAILURE(status)) { + + /* Truncate package and delete it */ + + package_object->package.count = i; + package_elements[i] = NULL; + acpi_ut_remove_reference(package_object); + return_ACPI_STATUS(status); + } + } + + /* Mark package data valid */ + + package_object->package.flags |= AOPOBJ_DATA_VALID; + + *internal_object = package_object; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_eobject_to_iobject + * + * PARAMETERS: external_object - The external object to be converted + * internal_object - Where the internal object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: Converts an external object to an internal object. + * + ******************************************************************************/ + +acpi_status +acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object, + union acpi_operand_object **internal_object) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject); + + if (external_object->type == ACPI_TYPE_PACKAGE) { + status = + acpi_ut_copy_epackage_to_ipackage(external_object, + internal_object); + } else { + /* + * Build a simple object (no nested objects) + */ + status = + acpi_ut_copy_esimple_to_isimple(external_object, + internal_object); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_simple_object + * + * PARAMETERS: source_desc - The internal object to be copied + * dest_desc - New target object + * + * RETURN: Status + * + * DESCRIPTION: Simple copy of one internal object to another. Reference count + * of the destination object is preserved. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, + union acpi_operand_object *dest_desc) +{ + u16 reference_count; + union acpi_operand_object *next_object; + + /* Save fields from destination that we don't want to overwrite */ + + reference_count = dest_desc->common.reference_count; + next_object = dest_desc->common.next_object; + + /* Copy the entire source object over the destination object */ + + ACPI_MEMCPY((char *)dest_desc, (char *)source_desc, + sizeof(union acpi_operand_object)); + + /* Restore the saved fields */ + + dest_desc->common.reference_count = reference_count; + dest_desc->common.next_object = next_object; + + /* New object is not static, regardless of source */ + + dest_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; + + /* Handle the objects with extra data */ + + switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { + case ACPI_TYPE_BUFFER: + /* + * Allocate and copy the actual buffer if and only if: + * 1) There is a valid buffer pointer + * 2) The buffer has a length > 0 + */ + if ((source_desc->buffer.pointer) && + (source_desc->buffer.length)) { + dest_desc->buffer.pointer = + ACPI_ALLOCATE(source_desc->buffer.length); + if (!dest_desc->buffer.pointer) { + return (AE_NO_MEMORY); + } + + /* Copy the actual buffer data */ + + ACPI_MEMCPY(dest_desc->buffer.pointer, + source_desc->buffer.pointer, + source_desc->buffer.length); + } + break; + + case ACPI_TYPE_STRING: + /* + * Allocate and copy the actual string if and only if: + * 1) There is a valid string pointer + * (Pointer to a NULL string is allowed) + */ + if (source_desc->string.pointer) { + dest_desc->string.pointer = + ACPI_ALLOCATE((acpi_size) source_desc->string. + length + 1); + if (!dest_desc->string.pointer) { + return (AE_NO_MEMORY); + } + + /* Copy the actual string data */ + + ACPI_MEMCPY(dest_desc->string.pointer, + source_desc->string.pointer, + (acpi_size) source_desc->string.length + 1); + } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + /* + * We copied the reference object, so we now must add a reference + * to the object pointed to by the reference + * + * DDBHandle reference (from Load/load_table) is a special reference, + * it does not have a Reference.Object, so does not need to + * increase the reference count + */ + if (source_desc->reference.class == ACPI_REFCLASS_TABLE) { + break; + } + + acpi_ut_add_reference(source_desc->reference.object); + break; + + case ACPI_TYPE_REGION: + /* + * We copied the Region Handler, so we now must add a reference + */ + if (dest_desc->region.handler) { + acpi_ut_add_reference(dest_desc->region.handler); + } + break; + + default: + /* Nothing to do for other simple objects */ + break; + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_ielement_to_ielement + * + * PARAMETERS: acpi_pkg_callback + * + * RETURN: Status + * + * DESCRIPTION: Copy one package element to another package element + * + ******************************************************************************/ + +static acpi_status +acpi_ut_copy_ielement_to_ielement(u8 object_type, + union acpi_operand_object *source_object, + union acpi_generic_state *state, + void *context) +{ + acpi_status status = AE_OK; + u32 this_index; + union acpi_operand_object **this_target_ptr; + union acpi_operand_object *target_object; + + ACPI_FUNCTION_ENTRY(); + + this_index = state->pkg.index; + this_target_ptr = (union acpi_operand_object **) + &state->pkg.dest_object->package.elements[this_index]; + + switch (object_type) { + case ACPI_COPY_TYPE_SIMPLE: + + /* A null source object indicates a (legal) null package element */ + + if (source_object) { + /* + * This is a simple object, just copy it + */ + target_object = + acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE + (source_object)); + if (!target_object) { + return (AE_NO_MEMORY); + } + + status = + acpi_ut_copy_simple_object(source_object, + target_object); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + + *this_target_ptr = target_object; + } else { + /* Pass through a null element */ + + *this_target_ptr = NULL; + } + break; + + case ACPI_COPY_TYPE_PACKAGE: + + /* + * This object is a package - go down another nesting level + * Create and build the package object + */ + target_object = + acpi_ut_create_package_object(source_object->package.count); + if (!target_object) { + return (AE_NO_MEMORY); + } + + target_object->common.flags = source_object->common.flags; + + /* Pass the new package object back to the package walk routine */ + + state->pkg.this_target_obj = target_object; + + /* Store the object pointer in the parent package object */ + + *this_target_ptr = target_object; + break; + + default: + return (AE_BAD_PARAMETER); + } + + return (status); + + error_exit: + acpi_ut_remove_reference(target_object); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_ipackage_to_ipackage + * + * PARAMETERS: *source_obj - Pointer to the source package object + * *dest_obj - Where the internal object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to copy an internal package object + * into another internal package object. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, + union acpi_operand_object *dest_obj, + struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage); + + dest_obj->common.type = ACPI_GET_OBJECT_TYPE(source_obj); + dest_obj->common.flags = source_obj->common.flags; + dest_obj->package.count = source_obj->package.count; + + /* + * Create the object array and walk the source package tree + */ + dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) + source_obj->package. + count + + 1) * sizeof(void *)); + if (!dest_obj->package.elements) { + ACPI_ERROR((AE_INFO, "Package allocation failure")); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Copy the package element-by-element by walking the package "tree". + * This handles nested packages of arbitrary depth. + */ + status = acpi_ut_walk_package_tree(source_obj, dest_obj, + acpi_ut_copy_ielement_to_ielement, + walk_state); + if (ACPI_FAILURE(status)) { + + /* On failure, delete the destination package object */ + + acpi_ut_remove_reference(dest_obj); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_iobject_to_iobject + * + * PARAMETERS: walk_state - Current walk state + * source_desc - The internal object to be copied + * dest_desc - Where the copied object is returned + * + * RETURN: Status + * + * DESCRIPTION: Copy an internal object to a new internal object + * + ******************************************************************************/ + +acpi_status +acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc, + union acpi_operand_object **dest_desc, + struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject); + + /* Create the top level object */ + + *dest_desc = + acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE(source_desc)); + if (!*dest_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Copy the object and possible subobjects */ + + if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_PACKAGE) { + status = + acpi_ut_copy_ipackage_to_ipackage(source_desc, *dest_desc, + walk_state); + } else { + status = acpi_ut_copy_simple_object(source_desc, *dest_desc); + } + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c new file mode 100644 index 000000000000..9a3538c497d0 --- /dev/null +++ b/drivers/acpi/acpica/utdebug.c @@ -0,0 +1,651 @@ +/****************************************************************************** + * + * Module Name: utdebug - Debug print routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utdebug") +#ifdef ACPI_DEBUG_OUTPUT +static acpi_thread_id acpi_gbl_prev_thread_id; +static char *acpi_gbl_fn_entry_str = "----Entry"; +static char *acpi_gbl_fn_exit_str = "----Exit-"; + +/* Local prototypes */ + +static const char *acpi_ut_trim_function_name(const char *function_name); + +/******************************************************************************* + * + * FUNCTION: acpi_ut_init_stack_ptr_trace + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Save the current CPU stack pointer at subsystem startup + * + ******************************************************************************/ + +void acpi_ut_init_stack_ptr_trace(void) +{ + acpi_size current_sp; + + acpi_gbl_entry_stack_pointer = ¤t_sp; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_track_stack_ptr + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Save the current CPU stack pointer + * + ******************************************************************************/ + +void acpi_ut_track_stack_ptr(void) +{ + acpi_size current_sp; + + if (¤t_sp < acpi_gbl_lowest_stack_pointer) { + acpi_gbl_lowest_stack_pointer = ¤t_sp; + } + + if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) { + acpi_gbl_deepest_nesting = acpi_gbl_nesting_level; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_trim_function_name + * + * PARAMETERS: function_name - Ascii string containing a procedure name + * + * RETURN: Updated pointer to the function name + * + * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present. + * This allows compiler macros such as __func__ to be used + * with no change to the debug output. + * + ******************************************************************************/ + +static const char *acpi_ut_trim_function_name(const char *function_name) +{ + + /* All Function names are longer than 4 chars, check is safe */ + + if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_MIXED) { + + /* This is the case where the original source has not been modified */ + + return (function_name + 4); + } + + if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_LOWER) { + + /* This is the case where the source has been 'linuxized' */ + + return (function_name + 5); + } + + return (function_name); +} + +/******************************************************************************* + * + * FUNCTION: acpi_debug_print + * + * PARAMETERS: requested_debug_level - Requested debug print level + * line_number - Caller's line number (for error output) + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID + * Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print error message with prefix consisting of the module name, + * line number, and component ID. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +acpi_debug_print(u32 requested_debug_level, + u32 line_number, + const char *function_name, + const char *module_name, + u32 component_id, const char *format, ...) +{ + acpi_thread_id thread_id; + va_list args; + + /* + * Stay silent if the debug level or component ID is disabled + */ + if (!(requested_debug_level & acpi_dbg_level) || + !(component_id & acpi_dbg_layer)) { + return; + } + + /* + * Thread tracking and context switch notification + */ + thread_id = acpi_os_get_thread_id(); + if (thread_id != acpi_gbl_prev_thread_id) { + if (ACPI_LV_THREADS & acpi_dbg_level) { + acpi_os_printf + ("\n**** Context Switch from TID %lX to TID %lX ****\n\n", + (unsigned long)acpi_gbl_prev_thread_id, + (unsigned long)thread_id); + } + + acpi_gbl_prev_thread_id = thread_id; + } + + /* + * Display the module name, current line number, thread ID (if requested), + * current procedure nesting level, and the current procedure name + */ + acpi_os_printf("%8s-%04ld ", module_name, line_number); + + if (ACPI_LV_THREADS & acpi_dbg_level) { + acpi_os_printf("[%04lX] ", (unsigned long)thread_id); + } + + acpi_os_printf("[%02ld] %-22.22s: ", + acpi_gbl_nesting_level, + acpi_ut_trim_function_name(function_name)); + + va_start(args, format); + acpi_os_vprintf(format, args); + va_end(args); +} + +ACPI_EXPORT_SYMBOL(acpi_debug_print) + +/******************************************************************************* + * + * FUNCTION: acpi_debug_print_raw + * + * PARAMETERS: requested_debug_level - Requested debug print level + * line_number - Caller's line number + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID + * Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print message with no headers. Has same interface as + * debug_print so that the same macros can be used. + * + ******************************************************************************/ +void ACPI_INTERNAL_VAR_XFACE +acpi_debug_print_raw(u32 requested_debug_level, + u32 line_number, + const char *function_name, + const char *module_name, + u32 component_id, const char *format, ...) +{ + va_list args; + + if (!(requested_debug_level & acpi_dbg_level) || + !(component_id & acpi_dbg_layer)) { + return; + } + + va_start(args, format); + acpi_os_vprintf(format, args); + va_end(args); +} + +ACPI_EXPORT_SYMBOL(acpi_debug_print_raw) + +/******************************************************************************* + * + * FUNCTION: acpi_ut_trace + * + * PARAMETERS: line_number - Caller's line number + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in debug_level + * + ******************************************************************************/ +void +acpi_ut_trace(u32 line_number, + const char *function_name, + const char *module_name, u32 component_id) +{ + + acpi_gbl_nesting_level++; + acpi_ut_track_stack_ptr(); + + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s\n", acpi_gbl_fn_entry_str); +} + +ACPI_EXPORT_SYMBOL(acpi_ut_trace) + +/******************************************************************************* + * + * FUNCTION: acpi_ut_trace_ptr + * + * PARAMETERS: line_number - Caller's line number + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID + * Pointer - Pointer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in debug_level + * + ******************************************************************************/ +void +acpi_ut_trace_ptr(u32 line_number, + const char *function_name, + const char *module_name, u32 component_id, void *pointer) +{ + acpi_gbl_nesting_level++; + acpi_ut_track_stack_ptr(); + + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s %p\n", acpi_gbl_fn_entry_str, pointer); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_trace_str + * + * PARAMETERS: line_number - Caller's line number + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID + * String - Additional string to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in debug_level + * + ******************************************************************************/ + +void +acpi_ut_trace_str(u32 line_number, + const char *function_name, + const char *module_name, u32 component_id, char *string) +{ + + acpi_gbl_nesting_level++; + acpi_ut_track_stack_ptr(); + + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s %s\n", acpi_gbl_fn_entry_str, string); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_trace_u32 + * + * PARAMETERS: line_number - Caller's line number + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID + * Integer - Integer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in debug_level + * + ******************************************************************************/ + +void +acpi_ut_trace_u32(u32 line_number, + const char *function_name, + const char *module_name, u32 component_id, u32 integer) +{ + + acpi_gbl_nesting_level++; + acpi_ut_track_stack_ptr(); + + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s %08X\n", acpi_gbl_fn_entry_str, integer); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_exit + * + * PARAMETERS: line_number - Caller's line number + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in debug_level + * + ******************************************************************************/ + +void +acpi_ut_exit(u32 line_number, + const char *function_name, + const char *module_name, u32 component_id) +{ + + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s\n", acpi_gbl_fn_exit_str); + + acpi_gbl_nesting_level--; +} + +ACPI_EXPORT_SYMBOL(acpi_ut_exit) + +/******************************************************************************* + * + * FUNCTION: acpi_ut_status_exit + * + * PARAMETERS: line_number - Caller's line number + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID + * Status - Exit status code + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in debug_level. Prints exit status also. + * + ******************************************************************************/ +void +acpi_ut_status_exit(u32 line_number, + const char *function_name, + const char *module_name, + u32 component_id, acpi_status status) +{ + + if (ACPI_SUCCESS(status)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %s\n", acpi_gbl_fn_exit_str, + acpi_format_exception(status)); + } else { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s ****Exception****: %s\n", + acpi_gbl_fn_exit_str, + acpi_format_exception(status)); + } + + acpi_gbl_nesting_level--; +} + +ACPI_EXPORT_SYMBOL(acpi_ut_status_exit) + +/******************************************************************************* + * + * FUNCTION: acpi_ut_value_exit + * + * PARAMETERS: line_number - Caller's line number + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID + * Value - Value to be printed with exit msg + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in debug_level. Prints exit value also. + * + ******************************************************************************/ +void +acpi_ut_value_exit(u32 line_number, + const char *function_name, + const char *module_name, + u32 component_id, acpi_integer value) +{ + + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str, + ACPI_FORMAT_UINT64(value)); + + acpi_gbl_nesting_level--; +} + +ACPI_EXPORT_SYMBOL(acpi_ut_value_exit) + +/******************************************************************************* + * + * FUNCTION: acpi_ut_ptr_exit + * + * PARAMETERS: line_number - Caller's line number + * function_name - Caller's procedure name + * module_name - Caller's module name + * component_id - Caller's component ID + * Ptr - Pointer to display + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in debug_level. Prints exit value also. + * + ******************************************************************************/ +void +acpi_ut_ptr_exit(u32 line_number, + const char *function_name, + const char *module_name, u32 component_id, u8 *ptr) +{ + + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, component_id, + "%s %p\n", acpi_gbl_fn_exit_str, ptr); + + acpi_gbl_nesting_level--; +} + +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_buffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Display - BYTE, WORD, DWORD, or QWORD display + * component_iD - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) +{ + u32 i = 0; + u32 j; + u32 temp32; + u8 buf_char; + + if (!buffer) { + acpi_os_printf("Null Buffer Pointer in DumpBuffer!\n"); + return; + } + + if ((count < 4) || (count & 0x01)) { + display = DB_BYTE_DISPLAY; + } + + /* Nasty little dump buffer routine! */ + + while (i < count) { + + /* Print current offset */ + + acpi_os_printf("%6.4X: ", i); + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) { + if (i + j >= count) { + + /* Dump fill spaces */ + + acpi_os_printf("%*s", ((display * 2) + 1), " "); + j += display; + continue; + } + + switch (display) { + case DB_BYTE_DISPLAY: + default: /* Default is BYTE display */ + + acpi_os_printf("%02X ", + buffer[(acpi_size) i + j]); + break; + + case DB_WORD_DISPLAY: + + ACPI_MOVE_16_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_os_printf("%04X ", temp32); + break; + + case DB_DWORD_DISPLAY: + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_os_printf("%08X ", temp32); + break; + + case DB_QWORD_DISPLAY: + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_os_printf("%08X", temp32); + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j + + 4]); + acpi_os_printf("%08X ", temp32); + break; + } + + j += display; + } + + /* + * Print the ASCII equivalent characters but watch out for the bad + * unprintable ones (printable chars are 0x20 through 0x7E) + */ + acpi_os_printf(" "); + for (j = 0; j < 16; j++) { + if (i + j >= count) { + acpi_os_printf("\n"); + return; + } + + buf_char = buffer[(acpi_size) i + j]; + if (ACPI_IS_PRINT(buf_char)) { + acpi_os_printf("%c", buf_char); + } else { + acpi_os_printf("."); + } + } + + /* Done with that line. */ + + acpi_os_printf("\n"); + i += 16; + } + + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_buffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Display - BYTE, WORD, DWORD, or QWORD display + * component_iD - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) +{ + + /* Only dump the buffer if tracing is enabled */ + + if (!((ACPI_LV_TABLES & acpi_dbg_level) && + (component_id & acpi_dbg_layer))) { + return; + } + + acpi_ut_dump_buffer2(buffer, count, display); +} diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c new file mode 100644 index 000000000000..5b4e3b1a7523 --- /dev/null +++ b/drivers/acpi/acpica/utdelete.c @@ -0,0 +1,677 @@ +/******************************************************************************* + * + * Module Name: utdelete - object deletion and reference count utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utdelete") + +/* Local prototypes */ +static void acpi_ut_delete_internal_obj(union acpi_operand_object *object); + +static void +acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action); + +/******************************************************************************* + * + * FUNCTION: acpi_ut_delete_internal_obj + * + * PARAMETERS: Object - Object to be deleted + * + * RETURN: None + * + * DESCRIPTION: Low level object deletion, after reference counts have been + * updated (All reference counts, including sub-objects!) + * + ******************************************************************************/ + +static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) +{ + void *obj_pointer = NULL; + union acpi_operand_object *handler_desc; + union acpi_operand_object *second_desc; + union acpi_operand_object *next_desc; + + ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object); + + if (!object) { + return_VOID; + } + + /* + * Must delete or free any pointers within the object that are not + * actual ACPI objects (for example, a raw buffer pointer). + */ + switch (ACPI_GET_OBJECT_TYPE(object)) { + case ACPI_TYPE_STRING: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "**** String %p, ptr %p\n", object, + object->string.pointer)); + + /* Free the actual string buffer */ + + if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { + + /* But only if it is NOT a pointer into an ACPI table */ + + obj_pointer = object->string.pointer; + } + break; + + case ACPI_TYPE_BUFFER: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "**** Buffer %p, ptr %p\n", object, + object->buffer.pointer)); + + /* Free the actual buffer */ + + if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { + + /* But only if it is NOT a pointer into an ACPI table */ + + obj_pointer = object->buffer.pointer; + } + break; + + case ACPI_TYPE_PACKAGE: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + " **** Package of count %X\n", + object->package.count)); + + /* + * Elements of the package are not handled here, they are deleted + * separately + */ + + /* Free the (variable length) element pointer array */ + + obj_pointer = object->package.elements; + break; + + /* + * These objects have a possible list of notify handlers. + * Device object also may have a GPE block. + */ + case ACPI_TYPE_DEVICE: + + if (object->device.gpe_block) { + (void)acpi_ev_delete_gpe_block(object->device. + gpe_block); + } + + /*lint -fallthrough */ + + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* Walk the notify handler list for this object */ + + handler_desc = object->common_notify.handler; + while (handler_desc) { + next_desc = handler_desc->address_space.next; + acpi_ut_remove_reference(handler_desc); + handler_desc = next_desc; + } + break; + + case ACPI_TYPE_MUTEX: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "***** Mutex %p, OS Mutex %p\n", + object, object->mutex.os_mutex)); + + if (object == acpi_gbl_global_lock_mutex) { + + /* Global Lock has extra semaphore */ + + (void) + acpi_os_delete_semaphore + (acpi_gbl_global_lock_semaphore); + acpi_gbl_global_lock_semaphore = NULL; + + acpi_os_delete_mutex(object->mutex.os_mutex); + acpi_gbl_global_lock_mutex = NULL; + } else { + acpi_ex_unlink_mutex(object); + acpi_os_delete_mutex(object->mutex.os_mutex); + } + break; + + case ACPI_TYPE_EVENT: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "***** Event %p, OS Semaphore %p\n", + object, object->event.os_semaphore)); + + (void)acpi_os_delete_semaphore(object->event.os_semaphore); + object->event.os_semaphore = NULL; + break; + + case ACPI_TYPE_METHOD: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "***** Method %p\n", object)); + + /* Delete the method mutex if it exists */ + + if (object->method.mutex) { + acpi_os_delete_mutex(object->method.mutex->mutex. + os_mutex); + acpi_ut_delete_object_desc(object->method.mutex); + object->method.mutex = NULL; + } + break; + + case ACPI_TYPE_REGION: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "***** Region %p\n", object)); + + second_desc = acpi_ns_get_secondary_object(object); + if (second_desc) { + /* + * Free the region_context if and only if the handler is one of the + * default handlers -- and therefore, we created the context object + * locally, it was not created by an external caller. + */ + handler_desc = object->region.handler; + if (handler_desc) { + if (handler_desc->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { + + /* Deactivate region and free region context */ + + if (handler_desc->address_space.setup) { + (void)handler_desc-> + address_space.setup(object, + ACPI_REGION_DEACTIVATE, + handler_desc-> + address_space. + context, + &second_desc-> + extra. + region_context); + } + } + + acpi_ut_remove_reference(handler_desc); + } + + /* Now we can free the Extra object */ + + acpi_ut_delete_object_desc(second_desc); + } + break; + + case ACPI_TYPE_BUFFER_FIELD: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "***** Buffer Field %p\n", object)); + + second_desc = acpi_ns_get_secondary_object(object); + if (second_desc) { + acpi_ut_delete_object_desc(second_desc); + } + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "***** Bank Field %p\n", object)); + + second_desc = acpi_ns_get_secondary_object(object); + if (second_desc) { + acpi_ut_delete_object_desc(second_desc); + } + break; + + default: + break; + } + + /* Free any allocated memory (pointer within the object) found above */ + + if (obj_pointer) { + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "Deleting Object Subptr %p\n", obj_pointer)); + ACPI_FREE(obj_pointer); + } + + /* Now the object can be safely deleted */ + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n", + object, acpi_ut_get_object_type_name(object))); + + acpi_ut_delete_object_desc(object); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_delete_internal_object_list + * + * PARAMETERS: obj_list - Pointer to the list to be deleted + * + * RETURN: None + * + * DESCRIPTION: This function deletes an internal object list, including both + * simple objects and package objects + * + ******************************************************************************/ + +void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list) +{ + union acpi_operand_object **internal_obj; + + ACPI_FUNCTION_TRACE(ut_delete_internal_object_list); + + /* Walk the null-terminated internal list */ + + for (internal_obj = obj_list; *internal_obj; internal_obj++) { + acpi_ut_remove_reference(*internal_obj); + } + + /* Free the combined parameter pointer list and object array */ + + ACPI_FREE(obj_list); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_update_ref_count + * + * PARAMETERS: Object - Object whose ref count is to be updated + * Action - What to do + * + * RETURN: New ref count + * + * DESCRIPTION: Modify the ref count and return it. + * + ******************************************************************************/ + +static void +acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) +{ + u16 count; + u16 new_count; + + ACPI_FUNCTION_NAME(ut_update_ref_count); + + if (!object) { + return; + } + + count = object->common.reference_count; + new_count = count; + + /* + * Perform the reference count action (increment, decrement, force delete) + */ + switch (action) { + case REF_INCREMENT: + + new_count++; + object->common.reference_count = new_count; + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, [Incremented]\n", + object, new_count)); + break; + + case REF_DECREMENT: + + if (count < 1) { + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, can't decrement! (Set to 0)\n", + object, new_count)); + + new_count = 0; + } else { + new_count--; + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, [Decremented]\n", + object, new_count)); + } + + if (ACPI_GET_OBJECT_TYPE(object) == ACPI_TYPE_METHOD) { + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "Method Obj %p Refs=%X, [Decremented]\n", + object, new_count)); + } + + object->common.reference_count = new_count; + if (new_count == 0) { + acpi_ut_delete_internal_obj(object); + } + break; + + case REF_FORCE_DELETE: + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, Force delete! (Set to 0)\n", + object, count)); + + new_count = 0; + object->common.reference_count = new_count; + acpi_ut_delete_internal_obj(object); + break; + + default: + + ACPI_ERROR((AE_INFO, "Unknown action (%X)", action)); + break; + } + + /* + * Sanity check the reference count, for debug purposes only. + * (A deleted object will have a huge reference count) + */ + if (count > ACPI_MAX_REFERENCE_COUNT) { + ACPI_WARNING((AE_INFO, + "Large Reference Count (%X) in object %p", count, + object)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_update_object_reference + * + * PARAMETERS: Object - Increment ref count for this object + * and all sub-objects + * Action - Either REF_INCREMENT or REF_DECREMENT or + * REF_FORCE_DELETE + * + * RETURN: Status + * + * DESCRIPTION: Increment the object reference count + * + * Object references are incremented when: + * 1) An object is attached to a Node (namespace object) + * 2) An object is copied (all subobjects must be incremented) + * + * Object references are decremented when: + * 1) An object is detached from an Node + * + ******************************************************************************/ + +acpi_status +acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) +{ + acpi_status status = AE_OK; + union acpi_generic_state *state_list = NULL; + union acpi_operand_object *next_object = NULL; + union acpi_generic_state *state; + u32 i; + + ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object); + + while (object) { + + /* Make sure that this isn't a namespace handle */ + + if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) { + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "Object %p is NS handle\n", object)); + return_ACPI_STATUS(AE_OK); + } + + /* + * All sub-objects must have their reference count incremented also. + * Different object types have different subobjects. + */ + switch (ACPI_GET_OBJECT_TYPE(object)) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + case ACPI_TYPE_THERMAL: + + /* Update the notify objects for these types (if present) */ + + acpi_ut_update_ref_count(object->common_notify. + system_notify, action); + acpi_ut_update_ref_count(object->common_notify. + device_notify, action); + break; + + case ACPI_TYPE_PACKAGE: + /* + * We must update all the sub-objects of the package, + * each of whom may have their own sub-objects. + */ + for (i = 0; i < object->package.count; i++) { + /* + * Push each element onto the stack for later processing. + * Note: There can be null elements within the package, + * these are simply ignored + */ + status = + acpi_ut_create_update_state_and_push + (object->package.elements[i], action, + &state_list); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + } + break; + + case ACPI_TYPE_BUFFER_FIELD: + + next_object = object->buffer_field.buffer_obj; + break; + + case ACPI_TYPE_LOCAL_REGION_FIELD: + + next_object = object->field.region_obj; + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + next_object = object->bank_field.bank_obj; + status = + acpi_ut_create_update_state_and_push(object-> + bank_field. + region_obj, + action, + &state_list); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + break; + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + next_object = object->index_field.index_obj; + status = + acpi_ut_create_update_state_and_push(object-> + index_field. + data_obj, + action, + &state_list); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + /* + * The target of an Index (a package, string, or buffer) or a named + * reference must track changes to the ref count of the index or + * target object. + */ + if ((object->reference.class == ACPI_REFCLASS_INDEX) || + (object->reference.class == ACPI_REFCLASS_NAME)) { + next_object = object->reference.object; + } + break; + + case ACPI_TYPE_REGION: + default: + break; /* No subobjects for all other types */ + } + + /* + * Now we can update the count in the main object. This can only + * happen after we update the sub-objects in case this causes the + * main object to be deleted. + */ + acpi_ut_update_ref_count(object, action); + object = NULL; + + /* Move on to the next object to be updated */ + + if (next_object) { + object = next_object; + next_object = NULL; + } else if (state_list) { + state = acpi_ut_pop_generic_state(&state_list); + object = state->update.object; + acpi_ut_delete_generic_state(state); + } + } + + return_ACPI_STATUS(AE_OK); + + error_exit: + + ACPI_EXCEPTION((AE_INFO, status, + "Could not update object reference count")); + + /* Free any stacked Update State objects */ + + while (state_list) { + state = acpi_ut_pop_generic_state(&state_list); + acpi_ut_delete_generic_state(state); + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_add_reference + * + * PARAMETERS: Object - Object whose reference count is to be + * incremented + * + * RETURN: None + * + * DESCRIPTION: Add one reference to an ACPI object + * + ******************************************************************************/ + +void acpi_ut_add_reference(union acpi_operand_object *object) +{ + + ACPI_FUNCTION_TRACE_PTR(ut_add_reference, object); + + /* Ensure that we have a valid object */ + + if (!acpi_ut_valid_internal_object(object)) { + return_VOID; + } + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "Obj %p Current Refs=%X [To Be Incremented]\n", + object, object->common.reference_count)); + + /* Increment the reference count */ + + (void)acpi_ut_update_object_reference(object, REF_INCREMENT); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_remove_reference + * + * PARAMETERS: Object - Object whose ref count will be decremented + * + * RETURN: None + * + * DESCRIPTION: Decrement the reference count of an ACPI internal object + * + ******************************************************************************/ + +void acpi_ut_remove_reference(union acpi_operand_object *object) +{ + + ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object); + + /* + * Allow a NULL pointer to be passed in, just ignore it. This saves + * each caller from having to check. Also, ignore NS nodes. + * + */ + if (!object || + (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED)) { + return_VOID; + } + + /* Ensure that we have a valid object */ + + if (!acpi_ut_valid_internal_object(object)) { + return_VOID; + } + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "Obj %p Current Refs=%X [To Be Decremented]\n", + object, object->common.reference_count)); + + /* + * Decrement the reference count, and only actually delete the object + * if the reference count becomes 0. (Must also decrement the ref count + * of all subobjects!) + */ + (void)acpi_ut_update_object_reference(object, REF_DECREMENT); + return_VOID; +} diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c new file mode 100644 index 000000000000..e1e438cd54a9 --- /dev/null +++ b/drivers/acpi/acpica/uteval.c @@ -0,0 +1,752 @@ +/****************************************************************************** + * + * Module Name: uteval - Object evaluation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("uteval") + +/* Local prototypes */ +static void +acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length); + +static acpi_status +acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, + struct acpi_compatible_id *one_cid); + +/* + * Strings supported by the _OSI predefined (internal) method. + */ +static char *acpi_interfaces_supported[] = { + /* Operating System Vendor Strings */ + + "Windows 2000", /* Windows 2000 */ + "Windows 2001", /* Windows XP */ + "Windows 2001 SP1", /* Windows XP SP1 */ + "Windows 2001 SP2", /* Windows XP SP2 */ + "Windows 2001.1", /* Windows Server 2003 */ + "Windows 2001.1 SP1", /* Windows Server 2003 SP1 - Added 03/2006 */ + "Windows 2006", /* Windows Vista - Added 03/2006 */ + + /* Feature Group Strings */ + + "Extended Address Space Descriptor" + /* + * All "optional" feature group strings (features that are implemented + * by the host) should be implemented in the host version of + * acpi_os_validate_interface and should not be added here. + */ +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_osi_implementation + * + * PARAMETERS: walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Implementation of the _OSI predefined control method + * + ******************************************************************************/ + +acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_operand_object *string_desc; + union acpi_operand_object *return_desc; + u32 i; + + ACPI_FUNCTION_TRACE(ut_osi_implementation); + + /* Validate the string input argument */ + + string_desc = walk_state->arguments[0].object; + if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) { + return_ACPI_STATUS(AE_TYPE); + } + + /* Create a return object */ + + return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!return_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Default return value is SUPPORTED */ + + return_desc->integer.value = ACPI_UINT32_MAX; + walk_state->return_desc = return_desc; + + /* Compare input string to static table of supported interfaces */ + + for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { + if (!ACPI_STRCMP + (string_desc->string.pointer, + acpi_interfaces_supported[i])) { + + /* The interface is supported */ + + return_ACPI_STATUS(AE_OK); + } + } + + /* + * Did not match the string in the static table, call the host OSL to + * check for a match with one of the optional strings (such as + * "Module Device", "3.0 Thermal Model", etc.) + */ + status = acpi_os_validate_interface(string_desc->string.pointer); + if (ACPI_SUCCESS(status)) { + + /* The interface is supported */ + + return_ACPI_STATUS(AE_OK); + } + + /* The interface is not supported */ + + return_desc->integer.value = 0; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_osi_invalidate + * + * PARAMETERS: interface_string + * + * RETURN: Status + * + * DESCRIPTION: invalidate string in pre-defiend _OSI string list + * + ******************************************************************************/ + +acpi_status acpi_osi_invalidate(char *interface) +{ + int i; + + for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { + if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i])) { + *acpi_interfaces_supported[i] = '\0'; + return AE_OK; + } + } + return AE_NOT_FOUND; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_evaluate_object + * + * PARAMETERS: prefix_node - Starting node + * Path - Path to object from starting node + * expected_return_types - Bitmap of allowed return types + * return_desc - Where a return value is stored + * + * RETURN: Status + * + * DESCRIPTION: Evaluates a namespace object and verifies the type of the + * return object. Common code that simplifies accessing objects + * that have required return objects of fixed types. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, + char *path, + u32 expected_return_btypes, + union acpi_operand_object **return_desc) +{ + struct acpi_evaluate_info *info; + acpi_status status; + u32 return_btype; + + ACPI_FUNCTION_TRACE(ut_evaluate_object); + + /* Allocate the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->prefix_node = prefix_node; + info->pathname = path; + + /* Evaluate the object/method */ + + status = acpi_ns_evaluate(info); + if (ACPI_FAILURE(status)) { + if (status == AE_NOT_FOUND) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[%4.4s.%s] was not found\n", + acpi_ut_get_node_name(prefix_node), + path)); + } else { + ACPI_ERROR_METHOD("Method execution failed", + prefix_node, path, status); + } + + goto cleanup; + } + + /* Did we get a return object? */ + + if (!info->return_object) { + if (expected_return_btypes) { + ACPI_ERROR_METHOD("No object was returned from", + prefix_node, path, AE_NOT_EXIST); + + status = AE_NOT_EXIST; + } + + goto cleanup; + } + + /* Map the return object type to the bitmapped type */ + + switch (ACPI_GET_OBJECT_TYPE(info->return_object)) { + case ACPI_TYPE_INTEGER: + return_btype = ACPI_BTYPE_INTEGER; + break; + + case ACPI_TYPE_BUFFER: + return_btype = ACPI_BTYPE_BUFFER; + break; + + case ACPI_TYPE_STRING: + return_btype = ACPI_BTYPE_STRING; + break; + + case ACPI_TYPE_PACKAGE: + return_btype = ACPI_BTYPE_PACKAGE; + break; + + default: + return_btype = 0; + break; + } + + if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) { + /* + * We received a return object, but one was not expected. This can + * happen frequently if the "implicit return" feature is enabled. + * Just delete the return object and return AE_OK. + */ + acpi_ut_remove_reference(info->return_object); + goto cleanup; + } + + /* Is the return object one of the expected types? */ + + if (!(expected_return_btypes & return_btype)) { + ACPI_ERROR_METHOD("Return object type is incorrect", + prefix_node, path, AE_TYPE); + + ACPI_ERROR((AE_INFO, + "Type returned from %s was incorrect: %s, expected Btypes: %X", + path, + acpi_ut_get_object_type_name(info->return_object), + expected_return_btypes)); + + /* On error exit, we must delete the return object */ + + acpi_ut_remove_reference(info->return_object); + status = AE_TYPE; + goto cleanup; + } + + /* Object type is OK, return it */ + + *return_desc = info->return_object; + + cleanup: + ACPI_FREE(info); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_evaluate_numeric_object + * + * PARAMETERS: object_name - Object name to be evaluated + * device_node - Node for the device + * Address - Where the value is returned + * + * RETURN: Status + * + * DESCRIPTION: Evaluates a numeric namespace object for a selected device + * and stores result in *Address. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_evaluate_numeric_object(char *object_name, + struct acpi_namespace_node *device_node, + acpi_integer * address) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object); + + status = acpi_ut_evaluate_object(device_node, object_name, + ACPI_BTYPE_INTEGER, &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the returned Integer */ + + *address = obj_desc->integer.value; + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_id_string + * + * PARAMETERS: Destination - Where to copy the string + * Source - Source string + * max_length - Length of the destination buffer + * + * RETURN: None + * + * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods. + * Performs removal of a leading asterisk if present -- workaround + * for a known issue on a bunch of machines. + * + ******************************************************************************/ + +static void +acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length) +{ + + /* + * Workaround for ID strings that have a leading asterisk. This construct + * is not allowed by the ACPI specification (ID strings must be + * alphanumeric), but enough existing machines have this embedded in their + * ID strings that the following code is useful. + */ + if (*source == '*') { + source++; + } + + /* Do the actual copy */ + + ACPI_STRNCPY(destination, source, max_length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_execute_HID + * + * PARAMETERS: device_node - Node for the device + * Hid - Where the HID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _HID control method that returns the hardware + * ID of the device. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_HID(struct acpi_namespace_node *device_node, + struct acpica_device_id *hid) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_execute_HID); + + status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, + &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + + /* Convert the Numeric HID to string */ + + acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value, + hid->value); + } else { + /* Copy the String HID from the returned object */ + + acpi_ut_copy_id_string(hid->value, obj_desc->string.pointer, + sizeof(hid->value)); + } + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_translate_one_cid + * + * PARAMETERS: obj_desc - _CID object, must be integer or string + * one_cid - Where the CID string is returned + * + * RETURN: Status + * + * DESCRIPTION: Return a numeric or string _CID value as a string. + * (Compatible ID) + * + * NOTE: Assumes a maximum _CID string length of + * ACPI_MAX_CID_LENGTH. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, + struct acpi_compatible_id *one_cid) +{ + + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_INTEGER: + + /* Convert the Numeric CID to string */ + + acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value, + one_cid->value); + return (AE_OK); + + case ACPI_TYPE_STRING: + + if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) { + return (AE_AML_STRING_LIMIT); + } + + /* Copy the String CID from the returned object */ + + acpi_ut_copy_id_string(one_cid->value, obj_desc->string.pointer, + ACPI_MAX_CID_LENGTH); + return (AE_OK); + + default: + + return (AE_TYPE); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_execute_CID + * + * PARAMETERS: device_node - Node for the device + * return_cid_list - Where the CID list is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _CID control method that returns one or more + * compatible hardware IDs for the device. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_CID(struct acpi_namespace_node * device_node, + struct acpi_compatible_id_list ** return_cid_list) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + u32 count; + u32 size; + struct acpi_compatible_id_list *cid_list; + u32 i; + + ACPI_FUNCTION_TRACE(ut_execute_CID); + + /* Evaluate the _CID method for this device */ + + status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING + | ACPI_BTYPE_PACKAGE, &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the number of _CIDs returned */ + + count = 1; + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + count = obj_desc->package.count; + } + + /* Allocate a worst-case buffer for the _CIDs */ + + size = (((count - 1) * sizeof(struct acpi_compatible_id)) + + sizeof(struct acpi_compatible_id_list)); + + cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); + if (!cid_list) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Init CID list */ + + cid_list->count = count; + cid_list->size = size; + + /* + * A _CID can return either a single compatible ID or a package of + * compatible IDs. Each compatible ID can be one of the following: + * 1) Integer (32 bit compressed EISA ID) or + * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss") + */ + + /* The _CID object can be either a single CID or a package (list) of CIDs */ + + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + + /* Translate each package element */ + + for (i = 0; i < count; i++) { + status = + acpi_ut_translate_one_cid(obj_desc->package. + elements[i], + &cid_list->id[i]); + if (ACPI_FAILURE(status)) { + break; + } + } + } else { + /* Only one CID, translate to a string */ + + status = acpi_ut_translate_one_cid(obj_desc, cid_list->id); + } + + /* Cleanup on error */ + + if (ACPI_FAILURE(status)) { + ACPI_FREE(cid_list); + } else { + *return_cid_list = cid_list; + } + + /* On exit, we must delete the _CID return object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_execute_UID + * + * PARAMETERS: device_node - Node for the device + * Uid - Where the UID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _UID control method that returns the hardware + * ID of the device. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_UID(struct acpi_namespace_node *device_node, + struct acpica_device_id *uid) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_execute_UID); + + status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, + &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + + /* Convert the Numeric UID to string */ + + acpi_ex_unsigned_integer_to_string(obj_desc->integer.value, + uid->value); + } else { + /* Copy the String UID from the returned object */ + + acpi_ut_copy_id_string(uid->value, obj_desc->string.pointer, + sizeof(uid->value)); + } + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_execute_STA + * + * PARAMETERS: device_node - Node for the device + * Flags - Where the status flags are returned + * + * RETURN: Status + * + * DESCRIPTION: Executes _STA for selected device and stores results in + * *Flags. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_execute_STA); + + status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA, + ACPI_BTYPE_INTEGER, &obj_desc); + if (ACPI_FAILURE(status)) { + if (AE_NOT_FOUND == status) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "_STA on %4.4s was not found, assuming device is present\n", + acpi_ut_get_node_name(device_node))); + + *flags = ACPI_UINT32_MAX; + status = AE_OK; + } + + return_ACPI_STATUS(status); + } + + /* Extract the status flags */ + + *flags = (u32) obj_desc->integer.value; + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_execute_Sxds + * + * PARAMETERS: device_node - Node for the device + * Flags - Where the status flags are returned + * + * RETURN: Status + * + * DESCRIPTION: Executes _STA for selected device and stores results in + * *Flags. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + u32 i; + + ACPI_FUNCTION_TRACE(ut_execute_sxds); + + for (i = 0; i < 4; i++) { + highest[i] = 0xFF; + status = acpi_ut_evaluate_object(device_node, + ACPI_CAST_PTR(char, + acpi_gbl_highest_dstate_names + [i]), + ACPI_BTYPE_INTEGER, &obj_desc); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "%s on Device %4.4s, %s\n", + ACPI_CAST_PTR(char, + acpi_gbl_highest_dstate_names + [i]), + acpi_ut_get_node_name + (device_node), + acpi_format_exception + (status))); + + return_ACPI_STATUS(status); + } + } else { + /* Extract the Dstate value */ + + highest[i] = (u8) obj_desc->integer.value; + + /* Delete the return object */ + + acpi_ut_remove_reference(obj_desc); + } + } + + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c new file mode 100644 index 000000000000..3e28d8c4045d --- /dev/null +++ b/drivers/acpi/acpica/utglobal.c @@ -0,0 +1,823 @@ +/****************************************************************************** + * + * Module Name: utglobal - Global variables for the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define DEFINE_ACPI_GLOBALS + +#include +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utglobal") + +/******************************************************************************* + * + * Static global variable initialization. + * + ******************************************************************************/ +/* + * We want the debug switches statically initialized so they + * are already set when the debugger is entered. + */ +/* Debug switch - level and trace mask */ +u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT; + +/* Debug switch - layer (component) mask */ + +u32 acpi_dbg_layer = 0; +u32 acpi_gbl_nesting_level = 0; + +/* Debugger globals */ + +u8 acpi_gbl_db_terminate_threads = FALSE; +u8 acpi_gbl_abort_method = FALSE; +u8 acpi_gbl_method_executing = FALSE; + +/* System flags */ + +u32 acpi_gbl_startup_flags = 0; + +/* System starts uninitialized */ + +u8 acpi_gbl_shutdown = TRUE; + +const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = { + "\\_S0_", + "\\_S1_", + "\\_S2_", + "\\_S3_", + "\\_S4_", + "\\_S5_" +}; + +const char *acpi_gbl_highest_dstate_names[4] = { + "_S1D", + "_S2D", + "_S3D", + "_S4D" +}; + +/******************************************************************************* + * + * FUNCTION: acpi_format_exception + * + * PARAMETERS: Status - The acpi_status code to be formatted + * + * RETURN: A string containing the exception text. A valid pointer is + * always returned. + * + * DESCRIPTION: This function translates an ACPI exception into an ASCII string + * It is here instead of utxface.c so it is always present. + * + ******************************************************************************/ + +const char *acpi_format_exception(acpi_status status) +{ + const char *exception = NULL; + + ACPI_FUNCTION_ENTRY(); + + exception = acpi_ut_validate_exception(status); + if (!exception) { + + /* Exception code was not recognized */ + + ACPI_ERROR((AE_INFO, + "Unknown exception code: 0x%8.8X", status)); + + exception = "UNKNOWN_STATUS_CODE"; + dump_stack(); + } + + return (ACPI_CAST_PTR(const char, exception)); +} + +ACPI_EXPORT_SYMBOL(acpi_format_exception) + +/******************************************************************************* + * + * Namespace globals + * + ******************************************************************************/ +/* + * Predefined ACPI Names (Built-in to the Interpreter) + * + * NOTES: + * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run + * during the initialization sequence. + * 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to + * perform a Notify() operation on it. + */ +const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = { + {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_SB_", ACPI_TYPE_DEVICE, NULL}, + {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_TZ_", ACPI_TYPE_THERMAL, NULL}, + {"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL}, + {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, + {"_GL_", ACPI_TYPE_MUTEX, (char *)1}, + +#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) + {"_OSI", ACPI_TYPE_METHOD, (char *)1}, +#endif + + /* Table terminator */ + + {NULL, ACPI_TYPE_ANY, NULL} +}; + +/* + * Properties of the ACPI Object Types, both internal and external. + * The table is indexed by values of acpi_object_type + */ +const u8 acpi_gbl_ns_properties[] = { + ACPI_NS_NORMAL, /* 00 Any */ + ACPI_NS_NORMAL, /* 01 Number */ + ACPI_NS_NORMAL, /* 02 String */ + ACPI_NS_NORMAL, /* 03 Buffer */ + ACPI_NS_NORMAL, /* 04 Package */ + ACPI_NS_NORMAL, /* 05 field_unit */ + ACPI_NS_NEWSCOPE, /* 06 Device */ + ACPI_NS_NORMAL, /* 07 Event */ + ACPI_NS_NEWSCOPE, /* 08 Method */ + ACPI_NS_NORMAL, /* 09 Mutex */ + ACPI_NS_NORMAL, /* 10 Region */ + ACPI_NS_NEWSCOPE, /* 11 Power */ + ACPI_NS_NEWSCOPE, /* 12 Processor */ + ACPI_NS_NEWSCOPE, /* 13 Thermal */ + ACPI_NS_NORMAL, /* 14 buffer_field */ + ACPI_NS_NORMAL, /* 15 ddb_handle */ + ACPI_NS_NORMAL, /* 16 Debug Object */ + ACPI_NS_NORMAL, /* 17 def_field */ + ACPI_NS_NORMAL, /* 18 bank_field */ + ACPI_NS_NORMAL, /* 19 index_field */ + ACPI_NS_NORMAL, /* 20 Reference */ + ACPI_NS_NORMAL, /* 21 Alias */ + ACPI_NS_NORMAL, /* 22 method_alias */ + ACPI_NS_NORMAL, /* 23 Notify */ + ACPI_NS_NORMAL, /* 24 Address Handler */ + ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */ + ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */ + ACPI_NS_NEWSCOPE, /* 27 Scope */ + ACPI_NS_NORMAL, /* 28 Extra */ + ACPI_NS_NORMAL, /* 29 Data */ + ACPI_NS_NORMAL /* 30 Invalid */ +}; + +/* Hex to ASCII conversion table */ + +static const char acpi_gbl_hex_to_ascii[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_hex_to_ascii_char + * + * PARAMETERS: Integer - Contains the hex digit + * Position - bit position of the digit within the + * integer (multiple of 4) + * + * RETURN: The converted Ascii character + * + * DESCRIPTION: Convert a hex digit to an Ascii character + * + ******************************************************************************/ + +char acpi_ut_hex_to_ascii_char(acpi_integer integer, u32 position) +{ + + return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); +} + +/****************************************************************************** + * + * Event and Hardware globals + * + ******************************************************************************/ + +struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] = { + /* Name Parent Register Register Bit Position Register Bit Mask */ + + /* ACPI_BITREG_TIMER_STATUS */ {ACPI_REGISTER_PM1_STATUS, + ACPI_BITPOSITION_TIMER_STATUS, + ACPI_BITMASK_TIMER_STATUS}, + /* ACPI_BITREG_BUS_MASTER_STATUS */ {ACPI_REGISTER_PM1_STATUS, + ACPI_BITPOSITION_BUS_MASTER_STATUS, + ACPI_BITMASK_BUS_MASTER_STATUS}, + /* ACPI_BITREG_GLOBAL_LOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, + ACPI_BITPOSITION_GLOBAL_LOCK_STATUS, + ACPI_BITMASK_GLOBAL_LOCK_STATUS}, + /* ACPI_BITREG_POWER_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, + ACPI_BITPOSITION_POWER_BUTTON_STATUS, + ACPI_BITMASK_POWER_BUTTON_STATUS}, + /* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, + ACPI_BITPOSITION_SLEEP_BUTTON_STATUS, + ACPI_BITMASK_SLEEP_BUTTON_STATUS}, + /* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, + ACPI_BITPOSITION_RT_CLOCK_STATUS, + ACPI_BITMASK_RT_CLOCK_STATUS}, + /* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, + ACPI_BITPOSITION_WAKE_STATUS, + ACPI_BITMASK_WAKE_STATUS}, + /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, + ACPI_BITPOSITION_PCIEXP_WAKE_STATUS, + ACPI_BITMASK_PCIEXP_WAKE_STATUS}, + + /* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, + ACPI_BITPOSITION_TIMER_ENABLE, + ACPI_BITMASK_TIMER_ENABLE}, + /* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, + ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE, + ACPI_BITMASK_GLOBAL_LOCK_ENABLE}, + /* ACPI_BITREG_POWER_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, + ACPI_BITPOSITION_POWER_BUTTON_ENABLE, + ACPI_BITMASK_POWER_BUTTON_ENABLE}, + /* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, + ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE, + ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, + /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, + ACPI_BITPOSITION_RT_CLOCK_ENABLE, + ACPI_BITMASK_RT_CLOCK_ENABLE}, + /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, + ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, + ACPI_BITMASK_PCIEXP_WAKE_DISABLE}, + + /* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, + ACPI_BITPOSITION_SCI_ENABLE, + ACPI_BITMASK_SCI_ENABLE}, + /* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL, + ACPI_BITPOSITION_BUS_MASTER_RLD, + ACPI_BITMASK_BUS_MASTER_RLD}, + /* ACPI_BITREG_GLOBAL_LOCK_RELEASE */ {ACPI_REGISTER_PM1_CONTROL, + ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE, + ACPI_BITMASK_GLOBAL_LOCK_RELEASE}, + /* ACPI_BITREG_SLEEP_TYPE_A */ {ACPI_REGISTER_PM1_CONTROL, + ACPI_BITPOSITION_SLEEP_TYPE_X, + ACPI_BITMASK_SLEEP_TYPE_X}, + /* ACPI_BITREG_SLEEP_TYPE_B */ {ACPI_REGISTER_PM1_CONTROL, + ACPI_BITPOSITION_SLEEP_TYPE_X, + ACPI_BITMASK_SLEEP_TYPE_X}, + /* ACPI_BITREG_SLEEP_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, + ACPI_BITPOSITION_SLEEP_ENABLE, + ACPI_BITMASK_SLEEP_ENABLE}, + + /* ACPI_BITREG_ARB_DIS */ {ACPI_REGISTER_PM2_CONTROL, + ACPI_BITPOSITION_ARB_DISABLE, + ACPI_BITMASK_ARB_DISABLE} +}; + +struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = { + /* ACPI_EVENT_PMTIMER */ {ACPI_BITREG_TIMER_STATUS, + ACPI_BITREG_TIMER_ENABLE, + ACPI_BITMASK_TIMER_STATUS, + ACPI_BITMASK_TIMER_ENABLE}, + /* ACPI_EVENT_GLOBAL */ {ACPI_BITREG_GLOBAL_LOCK_STATUS, + ACPI_BITREG_GLOBAL_LOCK_ENABLE, + ACPI_BITMASK_GLOBAL_LOCK_STATUS, + ACPI_BITMASK_GLOBAL_LOCK_ENABLE}, + /* ACPI_EVENT_POWER_BUTTON */ {ACPI_BITREG_POWER_BUTTON_STATUS, + ACPI_BITREG_POWER_BUTTON_ENABLE, + ACPI_BITMASK_POWER_BUTTON_STATUS, + ACPI_BITMASK_POWER_BUTTON_ENABLE}, + /* ACPI_EVENT_SLEEP_BUTTON */ {ACPI_BITREG_SLEEP_BUTTON_STATUS, + ACPI_BITREG_SLEEP_BUTTON_ENABLE, + ACPI_BITMASK_SLEEP_BUTTON_STATUS, + ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, + /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS, + ACPI_BITREG_RT_CLOCK_ENABLE, + ACPI_BITMASK_RT_CLOCK_STATUS, + ACPI_BITMASK_RT_CLOCK_ENABLE}, +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_region_name + * + * PARAMETERS: None. + * + * RETURN: Status + * + * DESCRIPTION: Translate a Space ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Region type decoding */ + +const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { + "SystemMemory", + "SystemIO", + "PCI_Config", + "EmbeddedControl", + "SMBus", + "SystemCMOS", + "PCIBARTarget", + "DataTable" +}; + +char *acpi_ut_get_region_name(u8 space_id) +{ + + if (space_id >= ACPI_USER_REGION_BEGIN) { + return ("UserDefinedRegion"); + } else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) { + return ("InvalidSpaceId"); + } + + return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_event_name + * + * PARAMETERS: None. + * + * RETURN: Status + * + * DESCRIPTION: Translate a Event ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Event type decoding */ + +static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { + "PM_Timer", + "GlobalLock", + "PowerButton", + "SleepButton", + "RealTimeClock", +}; + +char *acpi_ut_get_event_name(u32 event_id) +{ + + if (event_id > ACPI_EVENT_MAX) { + return ("InvalidEventID"); + } + + return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id])); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_type_name + * + * PARAMETERS: None. + * + * RETURN: Status + * + * DESCRIPTION: Translate a Type ID into a name string (Debug only) + * + ******************************************************************************/ + +/* + * Elements of acpi_gbl_ns_type_names below must match + * one-to-one with values of acpi_object_type + * + * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; + * when stored in a table it really means that we have thus far seen no + * evidence to indicate what type is actually going to be stored for this entry. + */ +static const char acpi_gbl_bad_type[] = "UNDEFINED"; + +/* Printable names of the ACPI object types */ + +static const char *acpi_gbl_ns_type_names[] = { + /* 00 */ "Untyped", + /* 01 */ "Integer", + /* 02 */ "String", + /* 03 */ "Buffer", + /* 04 */ "Package", + /* 05 */ "FieldUnit", + /* 06 */ "Device", + /* 07 */ "Event", + /* 08 */ "Method", + /* 09 */ "Mutex", + /* 10 */ "Region", + /* 11 */ "Power", + /* 12 */ "Processor", + /* 13 */ "Thermal", + /* 14 */ "BufferField", + /* 15 */ "DdbHandle", + /* 16 */ "DebugObject", + /* 17 */ "RegionField", + /* 18 */ "BankField", + /* 19 */ "IndexField", + /* 20 */ "Reference", + /* 21 */ "Alias", + /* 22 */ "MethodAlias", + /* 23 */ "Notify", + /* 24 */ "AddrHandler", + /* 25 */ "ResourceDesc", + /* 26 */ "ResourceFld", + /* 27 */ "Scope", + /* 28 */ "Extra", + /* 29 */ "Data", + /* 30 */ "Invalid" +}; + +char *acpi_ut_get_type_name(acpi_object_type type) +{ + + if (type > ACPI_TYPE_INVALID) { + return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); + } + + return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type])); +} + +char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) +{ + + if (!obj_desc) { + return ("[NULL Object Descriptor]"); + } + + return (acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc))); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_node_name + * + * PARAMETERS: Object - A namespace node + * + * RETURN: Pointer to a string + * + * DESCRIPTION: Validate the node and return the node's ACPI name. + * + ******************************************************************************/ + +char *acpi_ut_get_node_name(void *object) +{ + struct acpi_namespace_node *node = (struct acpi_namespace_node *)object; + + /* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */ + + if (!object) { + return ("NULL"); + } + + /* Check for Root node */ + + if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) { + return ("\"\\\" "); + } + + /* Descriptor must be a namespace node */ + + if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { + return ("####"); + } + + /* Name must be a valid ACPI name */ + + if (!acpi_ut_valid_acpi_name(node->name.integer)) { + node->name.integer = acpi_ut_repair_name(node->name.ascii); + } + + /* Return the name */ + + return (node->name.ascii); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_descriptor_name + * + * PARAMETERS: Object - An ACPI object + * + * RETURN: Pointer to a string + * + * DESCRIPTION: Validate object and return the descriptor type + * + ******************************************************************************/ + +/* Printable names of object descriptor types */ + +static const char *acpi_gbl_desc_type_names[] = { + /* 00 */ "Invalid", + /* 01 */ "Cached", + /* 02 */ "State-Generic", + /* 03 */ "State-Update", + /* 04 */ "State-Package", + /* 05 */ "State-Control", + /* 06 */ "State-RootParseScope", + /* 07 */ "State-ParseScope", + /* 08 */ "State-WalkScope", + /* 09 */ "State-Result", + /* 10 */ "State-Notify", + /* 11 */ "State-Thread", + /* 12 */ "Walk", + /* 13 */ "Parser", + /* 14 */ "Operand", + /* 15 */ "Node" +}; + +char *acpi_ut_get_descriptor_name(void *object) +{ + + if (!object) { + return ("NULL OBJECT"); + } + + if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) { + return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); + } + + return (ACPI_CAST_PTR(char, + acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE + (object)])); + +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_reference_name + * + * PARAMETERS: Object - An ACPI reference object + * + * RETURN: Pointer to a string + * + * DESCRIPTION: Decode a reference object sub-type to a string. + * + ******************************************************************************/ + +/* Printable names of reference object sub-types */ + +static const char *acpi_gbl_ref_class_names[] = { + /* 00 */ "Local", + /* 01 */ "Argument", + /* 02 */ "RefOf", + /* 03 */ "Index", + /* 04 */ "DdbHandle", + /* 05 */ "Named Object", + /* 06 */ "Debug" +}; + +const char *acpi_ut_get_reference_name(union acpi_operand_object *object) +{ + if (!object) + return "NULL Object"; + + if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) + return "Not an Operand object"; + + if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE) + return "Not a Reference object"; + + if (object->reference.class > ACPI_REFCLASS_MAX) + return "Unknown Reference class"; + + return acpi_gbl_ref_class_names[object->reference.class]; +} + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/* + * Strings and procedures used for debug only + */ + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_mutex_name + * + * PARAMETERS: mutex_id - The predefined ID for this mutex. + * + * RETURN: String containing the name of the mutex. Always returns a valid + * pointer. + * + * DESCRIPTION: Translate a mutex ID into a name string (Debug only) + * + ******************************************************************************/ + +char *acpi_ut_get_mutex_name(u32 mutex_id) +{ + + if (mutex_id > ACPI_MAX_MUTEX) { + return ("Invalid Mutex ID"); + } + + return (acpi_gbl_mutex_names[mutex_id]); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_notify_name + * + * PARAMETERS: notify_value - Value from the Notify() request + * + * RETURN: String corresponding to the Notify Value. + * + * DESCRIPTION: Translate a Notify Value to a notify namestring. + * + ******************************************************************************/ + +/* Names for Notify() values, used for debug output */ + +static const char *acpi_gbl_notify_value_names[] = { + "Bus Check", + "Device Check", + "Device Wake", + "Eject Request", + "Device Check Light", + "Frequency Mismatch", + "Bus Mode Mismatch", + "Power Fault", + "Capabilities Check", + "Device PLD Check", + "Reserved", + "System Locality Update" +}; + +const char *acpi_ut_get_notify_name(u32 notify_value) +{ + + if (notify_value <= ACPI_NOTIFY_MAX) { + return (acpi_gbl_notify_value_names[notify_value]); + } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { + return ("Reserved"); + } else { /* Greater or equal to 0x80 */ + + return ("**Device Specific**"); + } +} +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_object_type + * + * PARAMETERS: Type - Object type to be validated + * + * RETURN: TRUE if valid object type, FALSE otherwise + * + * DESCRIPTION: Validate an object type + * + ******************************************************************************/ + +u8 acpi_ut_valid_object_type(acpi_object_type type) +{ + + if (type > ACPI_TYPE_LOCAL_MAX) { + + /* Note: Assumes all TYPEs are contiguous (external/local) */ + + return (FALSE); + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_init_globals + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Init library globals. All globals that require specific + * initialization should be initialized here! + * + ******************************************************************************/ + +acpi_status acpi_ut_init_globals(void) +{ + acpi_status status; + u32 i; + + ACPI_FUNCTION_TRACE(ut_init_globals); + + /* Create all memory caches */ + + status = acpi_ut_create_caches(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Mutex locked flags */ + + for (i = 0; i < ACPI_NUM_MUTEX; i++) { + acpi_gbl_mutex_info[i].mutex = NULL; + acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[i].use_count = 0; + } + + for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { + acpi_gbl_owner_id_mask[i] = 0; + } + acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; /* Last ID is never valid */ + + /* GPE support */ + + acpi_gbl_gpe_xrupt_list_head = NULL; + acpi_gbl_gpe_fadt_blocks[0] = NULL; + acpi_gbl_gpe_fadt_blocks[1] = NULL; + acpi_current_gpe_count = 0; + + /* Global handlers */ + + acpi_gbl_system_notify.handler = NULL; + acpi_gbl_device_notify.handler = NULL; + acpi_gbl_exception_handler = NULL; + acpi_gbl_init_handler = NULL; + acpi_gbl_table_handler = NULL; + + /* Global Lock support */ + + acpi_gbl_global_lock_semaphore = NULL; + acpi_gbl_global_lock_mutex = NULL; + acpi_gbl_global_lock_acquired = FALSE; + acpi_gbl_global_lock_handle = 0; + acpi_gbl_global_lock_present = FALSE; + + /* Miscellaneous variables */ + + acpi_gbl_cm_single_step = FALSE; + acpi_gbl_db_terminate_threads = FALSE; + acpi_gbl_shutdown = FALSE; + acpi_gbl_ns_lookup_count = 0; + acpi_gbl_ps_find_count = 0; + acpi_gbl_acpi_hardware_present = TRUE; + acpi_gbl_last_owner_id_index = 0; + acpi_gbl_next_owner_id_offset = 0; + acpi_gbl_trace_method_name = 0; + acpi_gbl_trace_dbg_level = 0; + acpi_gbl_trace_dbg_layer = 0; + acpi_gbl_debugger_configuration = DEBUGGER_THREADING; + acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; + + /* Hardware oriented */ + + acpi_gbl_events_initialized = FALSE; + acpi_gbl_system_awake_and_running = TRUE; + + /* Namespace */ + + acpi_gbl_root_node = NULL; + acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; + acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; + acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE; + acpi_gbl_root_node_struct.child = NULL; + acpi_gbl_root_node_struct.peer = NULL; + acpi_gbl_root_node_struct.object = NULL; + acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST; + +#ifdef ACPI_DEBUG_OUTPUT + acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); +#endif + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + acpi_gbl_display_final_mem_stats = FALSE; +#endif + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) +ACPI_EXPORT_SYMBOL(acpi_dbg_level) +ACPI_EXPORT_SYMBOL(acpi_dbg_layer) +ACPI_EXPORT_SYMBOL(acpi_current_gpe_count) diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c new file mode 100644 index 000000000000..9316ec36a836 --- /dev/null +++ b/drivers/acpi/acpica/utinit.c @@ -0,0 +1,152 @@ +/****************************************************************************** + * + * Module Name: utinit - Common ACPI subsystem initialization + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utinit") + +/* Local prototypes */ +static void acpi_ut_terminate(void); + +/****************************************************************************** + * + * FUNCTION: acpi_ut_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Free global memory + * + ******************************************************************************/ + +static void acpi_ut_terminate(void) +{ + struct acpi_gpe_block_info *gpe_block; + struct acpi_gpe_block_info *next_gpe_block; + struct acpi_gpe_xrupt_info *gpe_xrupt_info; + struct acpi_gpe_xrupt_info *next_gpe_xrupt_info; + + ACPI_FUNCTION_TRACE(ut_terminate); + + /* Free global GPE blocks and related info structures */ + + gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; + while (gpe_xrupt_info) { + gpe_block = gpe_xrupt_info->gpe_block_list_head; + while (gpe_block) { + next_gpe_block = gpe_block->next; + ACPI_FREE(gpe_block->event_info); + ACPI_FREE(gpe_block->register_info); + ACPI_FREE(gpe_block); + + gpe_block = next_gpe_block; + } + next_gpe_xrupt_info = gpe_xrupt_info->next; + ACPI_FREE(gpe_xrupt_info); + gpe_xrupt_info = next_gpe_xrupt_info; + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_subsystem_shutdown + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Shutdown the various subsystems. Don't delete the mutex + * objects here -- because the AML debugger may be still running. + * + ******************************************************************************/ + +void acpi_ut_subsystem_shutdown(void) +{ + + ACPI_FUNCTION_TRACE(ut_subsystem_shutdown); + + /* Just exit if subsystem is already shutdown */ + + if (acpi_gbl_shutdown) { + ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated")); + return_VOID; + } + + /* Subsystem appears active, go ahead and shut it down */ + + acpi_gbl_shutdown = TRUE; + acpi_gbl_startup_flags = 0; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); + +#ifndef ACPI_ASL_COMPILER + + /* Close the acpi_event Handling */ + + acpi_ev_terminate(); +#endif + + /* Close the Namespace */ + + acpi_ns_terminate(); + + /* Delete the ACPI tables */ + + acpi_tb_terminate(); + + /* Close the globals */ + + acpi_ut_terminate(); + + /* Purge the local caches */ + + (void)acpi_ut_delete_caches(); + return_VOID; +} diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c new file mode 100644 index 000000000000..616d7b271c9a --- /dev/null +++ b/drivers/acpi/acpica/utmath.c @@ -0,0 +1,312 @@ +/******************************************************************************* + * + * Module Name: utmath - Integer math support routines + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utmath") + +/* + * Support for double-precision integer divide. This code is included here + * in order to support kernel environments where the double-precision math + * library is not available. + */ +#ifndef ACPI_USE_NATIVE_DIVIDE +/******************************************************************************* + * + * FUNCTION: acpi_ut_short_divide + * + * PARAMETERS: Dividend - 64-bit dividend + * Divisor - 32-bit divisor + * out_quotient - Pointer to where the quotient is returned + * out_remainder - Pointer to where the remainder is returned + * + * RETURN: Status (Checks for divide-by-zero) + * + * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits) + * divide and modulo. The result is a 64-bit quotient and a + * 32-bit remainder. + * + ******************************************************************************/ +acpi_status +acpi_ut_short_divide(acpi_integer dividend, + u32 divisor, + acpi_integer * out_quotient, u32 * out_remainder) +{ + union uint64_overlay dividend_ovl; + union uint64_overlay quotient; + u32 remainder32; + + ACPI_FUNCTION_TRACE(ut_short_divide); + + /* Always check for a zero divisor */ + + if (divisor == 0) { + ACPI_ERROR((AE_INFO, "Divide by zero")); + return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); + } + + dividend_ovl.full = dividend; + + /* + * The quotient is 64 bits, the remainder is always 32 bits, + * and is generated by the second divide. + */ + ACPI_DIV_64_BY_32(0, dividend_ovl.part.hi, divisor, + quotient.part.hi, remainder32); + ACPI_DIV_64_BY_32(remainder32, dividend_ovl.part.lo, divisor, + quotient.part.lo, remainder32); + + /* Return only what was requested */ + + if (out_quotient) { + *out_quotient = quotient.full; + } + if (out_remainder) { + *out_remainder = remainder32; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_divide + * + * PARAMETERS: in_dividend - Dividend + * in_divisor - Divisor + * out_quotient - Pointer to where the quotient is returned + * out_remainder - Pointer to where the remainder is returned + * + * RETURN: Status (Checks for divide-by-zero) + * + * DESCRIPTION: Perform a divide and modulo. + * + ******************************************************************************/ + +acpi_status +acpi_ut_divide(acpi_integer in_dividend, + acpi_integer in_divisor, + acpi_integer * out_quotient, acpi_integer * out_remainder) +{ + union uint64_overlay dividend; + union uint64_overlay divisor; + union uint64_overlay quotient; + union uint64_overlay remainder; + union uint64_overlay normalized_dividend; + union uint64_overlay normalized_divisor; + u32 partial1; + union uint64_overlay partial2; + union uint64_overlay partial3; + + ACPI_FUNCTION_TRACE(ut_divide); + + /* Always check for a zero divisor */ + + if (in_divisor == 0) { + ACPI_ERROR((AE_INFO, "Divide by zero")); + return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); + } + + divisor.full = in_divisor; + dividend.full = in_dividend; + if (divisor.part.hi == 0) { + /* + * 1) Simplest case is where the divisor is 32 bits, we can + * just do two divides + */ + remainder.part.hi = 0; + + /* + * The quotient is 64 bits, the remainder is always 32 bits, + * and is generated by the second divide. + */ + ACPI_DIV_64_BY_32(0, dividend.part.hi, divisor.part.lo, + quotient.part.hi, partial1); + ACPI_DIV_64_BY_32(partial1, dividend.part.lo, divisor.part.lo, + quotient.part.lo, remainder.part.lo); + } + + else { + /* + * 2) The general case where the divisor is a full 64 bits + * is more difficult + */ + quotient.part.hi = 0; + normalized_dividend = dividend; + normalized_divisor = divisor; + + /* Normalize the operands (shift until the divisor is < 32 bits) */ + + do { + ACPI_SHIFT_RIGHT_64(normalized_divisor.part.hi, + normalized_divisor.part.lo); + ACPI_SHIFT_RIGHT_64(normalized_dividend.part.hi, + normalized_dividend.part.lo); + + } while (normalized_divisor.part.hi != 0); + + /* Partial divide */ + + ACPI_DIV_64_BY_32(normalized_dividend.part.hi, + normalized_dividend.part.lo, + normalized_divisor.part.lo, + quotient.part.lo, partial1); + + /* + * The quotient is always 32 bits, and simply requires adjustment. + * The 64-bit remainder must be generated. + */ + partial1 = quotient.part.lo * divisor.part.hi; + partial2.full = + (acpi_integer) quotient.part.lo * divisor.part.lo; + partial3.full = (acpi_integer) partial2.part.hi + partial1; + + remainder.part.hi = partial3.part.lo; + remainder.part.lo = partial2.part.lo; + + if (partial3.part.hi == 0) { + if (partial3.part.lo >= dividend.part.hi) { + if (partial3.part.lo == dividend.part.hi) { + if (partial2.part.lo > dividend.part.lo) { + quotient.part.lo--; + remainder.full -= divisor.full; + } + } else { + quotient.part.lo--; + remainder.full -= divisor.full; + } + } + + remainder.full = remainder.full - dividend.full; + remainder.part.hi = (u32) - ((s32) remainder.part.hi); + remainder.part.lo = (u32) - ((s32) remainder.part.lo); + + if (remainder.part.lo) { + remainder.part.hi--; + } + } + } + + /* Return only what was requested */ + + if (out_quotient) { + *out_quotient = quotient.full; + } + if (out_remainder) { + *out_remainder = remainder.full; + } + + return_ACPI_STATUS(AE_OK); +} + +#else +/******************************************************************************* + * + * FUNCTION: acpi_ut_short_divide, acpi_ut_divide + * + * PARAMETERS: See function headers above + * + * DESCRIPTION: Native versions of the ut_divide functions. Use these if either + * 1) The target is a 64-bit platform and therefore 64-bit + * integer math is supported directly by the machine. + * 2) The target is a 32-bit or 16-bit platform, and the + * double-precision integer math library is available to + * perform the divide. + * + ******************************************************************************/ +acpi_status +acpi_ut_short_divide(acpi_integer in_dividend, + u32 divisor, + acpi_integer * out_quotient, u32 * out_remainder) +{ + + ACPI_FUNCTION_TRACE(ut_short_divide); + + /* Always check for a zero divisor */ + + if (divisor == 0) { + ACPI_ERROR((AE_INFO, "Divide by zero")); + return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); + } + + /* Return only what was requested */ + + if (out_quotient) { + *out_quotient = in_dividend / divisor; + } + if (out_remainder) { + *out_remainder = (u32) (in_dividend % divisor); + } + + return_ACPI_STATUS(AE_OK); +} + +acpi_status +acpi_ut_divide(acpi_integer in_dividend, + acpi_integer in_divisor, + acpi_integer * out_quotient, acpi_integer * out_remainder) +{ + ACPI_FUNCTION_TRACE(ut_divide); + + /* Always check for a zero divisor */ + + if (in_divisor == 0) { + ACPI_ERROR((AE_INFO, "Divide by zero")); + return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); + } + + /* Return only what was requested */ + + if (out_quotient) { + *out_quotient = in_dividend / in_divisor; + } + if (out_remainder) { + *out_remainder = in_dividend % in_divisor; + } + + return_ACPI_STATUS(AE_OK); +} + +#endif diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c new file mode 100644 index 000000000000..8f8b407142ee --- /dev/null +++ b/drivers/acpi/acpica/utmisc.c @@ -0,0 +1,1093 @@ +/******************************************************************************* + * + * Module Name: utmisc - common utility procedures + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include + +#include +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utmisc") + +/******************************************************************************* + * + * FUNCTION: acpi_ut_validate_exception + * + * PARAMETERS: Status - The acpi_status code to be formatted + * + * RETURN: A string containing the exception text. NULL if exception is + * not valid. + * + * DESCRIPTION: This function validates and translates an ACPI exception into + * an ASCII string. + * + ******************************************************************************/ +const char *acpi_ut_validate_exception(acpi_status status) +{ + u32 sub_status; + const char *exception = NULL; + + ACPI_FUNCTION_ENTRY(); + + /* + * Status is composed of two parts, a "type" and an actual code + */ + sub_status = (status & ~AE_CODE_MASK); + + switch (status & AE_CODE_MASK) { + case AE_CODE_ENVIRONMENTAL: + + if (sub_status <= AE_CODE_ENV_MAX) { + exception = acpi_gbl_exception_names_env[sub_status]; + } + break; + + case AE_CODE_PROGRAMMER: + + if (sub_status <= AE_CODE_PGM_MAX) { + exception = acpi_gbl_exception_names_pgm[sub_status]; + } + break; + + case AE_CODE_ACPI_TABLES: + + if (sub_status <= AE_CODE_TBL_MAX) { + exception = acpi_gbl_exception_names_tbl[sub_status]; + } + break; + + case AE_CODE_AML: + + if (sub_status <= AE_CODE_AML_MAX) { + exception = acpi_gbl_exception_names_aml[sub_status]; + } + break; + + case AE_CODE_CONTROL: + + if (sub_status <= AE_CODE_CTRL_MAX) { + exception = acpi_gbl_exception_names_ctrl[sub_status]; + } + break; + + default: + break; + } + + return (ACPI_CAST_PTR(const char, exception)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_is_aml_table + * + * PARAMETERS: Table - An ACPI table + * + * RETURN: TRUE if table contains executable AML; FALSE otherwise + * + * DESCRIPTION: Check ACPI Signature for a table that contains AML code. + * Currently, these are DSDT,SSDT,PSDT. All other table types are + * data tables that do not contain AML code. + * + ******************************************************************************/ + +u8 acpi_ut_is_aml_table(struct acpi_table_header *table) +{ + + /* These are the only tables that contain executable AML */ + + if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) || + ACPI_COMPARE_NAME(table->signature, ACPI_SIG_PSDT) || + ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) { + return (TRUE); + } + + return (FALSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate_owner_id + * + * PARAMETERS: owner_id - Where the new owner ID is returned + * + * RETURN: Status + * + * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to + * track objects created by the table or method, to be deleted + * when the method exits or the table is unloaded. + * + ******************************************************************************/ + +acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) +{ + u32 i; + u32 j; + u32 k; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_allocate_owner_id); + + /* Guard against multiple allocations of ID to the same location */ + + if (*owner_id) { + ACPI_ERROR((AE_INFO, "Owner ID [%2.2X] already exists", + *owner_id)); + return_ACPI_STATUS(AE_ALREADY_EXISTS); + } + + /* Mutex for the global ID mask */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Find a free owner ID, cycle through all possible IDs on repeated + * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have + * to be scanned twice. + */ + for (i = 0, j = acpi_gbl_last_owner_id_index; + i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { + if (j >= ACPI_NUM_OWNERID_MASKS) { + j = 0; /* Wraparound to start of mask array */ + } + + for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { + if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { + + /* There are no free IDs in this mask */ + + break; + } + + if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { + /* + * Found a free ID. The actual ID is the bit index plus one, + * making zero an invalid Owner ID. Save this as the last ID + * allocated and update the global ID mask. + */ + acpi_gbl_owner_id_mask[j] |= (1 << k); + + acpi_gbl_last_owner_id_index = (u8) j; + acpi_gbl_next_owner_id_offset = (u8) (k + 1); + + /* + * Construct encoded ID from the index and bit position + * + * Note: Last [j].k (bit 255) is never used and is marked + * permanently allocated (prevents +1 overflow) + */ + *owner_id = + (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); + + ACPI_DEBUG_PRINT((ACPI_DB_VALUES, + "Allocated OwnerId: %2.2X\n", + (unsigned int)*owner_id)); + goto exit; + } + } + + acpi_gbl_next_owner_id_offset = 0; + } + + /* + * All owner_ids have been allocated. This typically should + * not happen since the IDs are reused after deallocation. The IDs are + * allocated upon table load (one per table) and method execution, and + * they are released when a table is unloaded or a method completes + * execution. + * + * If this error happens, there may be very deep nesting of invoked control + * methods, or there may be a bug where the IDs are not released. + */ + status = AE_OWNER_ID_LIMIT; + ACPI_ERROR((AE_INFO, + "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); + + exit: + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_release_owner_id + * + * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_iD + * + * RETURN: None. No error is returned because we are either exiting a + * control method or unloading a table. Either way, we would + * ignore any error anyway. + * + * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 + * + ******************************************************************************/ + +void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) +{ + acpi_owner_id owner_id = *owner_id_ptr; + acpi_status status; + u32 index; + u32 bit; + + ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); + + /* Always clear the input owner_id (zero is an invalid ID) */ + + *owner_id_ptr = 0; + + /* Zero is not a valid owner_iD */ + + if (owner_id == 0) { + ACPI_ERROR((AE_INFO, "Invalid OwnerId: %2.2X", owner_id)); + return_VOID; + } + + /* Mutex for the global ID mask */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return_VOID; + } + + /* Normalize the ID to zero */ + + owner_id--; + + /* Decode ID to index/offset pair */ + + index = ACPI_DIV_32(owner_id); + bit = 1 << ACPI_MOD_32(owner_id); + + /* Free the owner ID only if it is valid */ + + if (acpi_gbl_owner_id_mask[index] & bit) { + acpi_gbl_owner_id_mask[index] ^= bit; + } else { + ACPI_ERROR((AE_INFO, + "Release of non-allocated OwnerId: %2.2X", + owner_id + 1)); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strupr (strupr) + * + * PARAMETERS: src_string - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to uppercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ + +void acpi_ut_strupr(char *src_string) +{ + char *string; + + ACPI_FUNCTION_ENTRY(); + + if (!src_string) { + return; + } + + /* Walk entire string, uppercasing the letters */ + + for (string = src_string; *string; string++) { + *string = (char)ACPI_TOUPPER(*string); + } + + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_print_string + * + * PARAMETERS: String - Null terminated ASCII string + * max_length - Maximum output length + * + * RETURN: None + * + * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape + * sequences. + * + ******************************************************************************/ + +void acpi_ut_print_string(char *string, u8 max_length) +{ + u32 i; + + if (!string) { + acpi_os_printf("<\"NULL STRING PTR\">"); + return; + } + + acpi_os_printf("\""); + for (i = 0; string[i] && (i < max_length); i++) { + + /* Escape sequences */ + + switch (string[i]) { + case 0x07: + acpi_os_printf("\\a"); /* BELL */ + break; + + case 0x08: + acpi_os_printf("\\b"); /* BACKSPACE */ + break; + + case 0x0C: + acpi_os_printf("\\f"); /* FORMFEED */ + break; + + case 0x0A: + acpi_os_printf("\\n"); /* LINEFEED */ + break; + + case 0x0D: + acpi_os_printf("\\r"); /* CARRIAGE RETURN */ + break; + + case 0x09: + acpi_os_printf("\\t"); /* HORIZONTAL TAB */ + break; + + case 0x0B: + acpi_os_printf("\\v"); /* VERTICAL TAB */ + break; + + case '\'': /* Single Quote */ + case '\"': /* Double Quote */ + case '\\': /* Backslash */ + acpi_os_printf("\\%c", (int)string[i]); + break; + + default: + + /* Check for printable character or hex escape */ + + if (ACPI_IS_PRINT(string[i])) { + /* This is a normal character */ + + acpi_os_printf("%c", (int)string[i]); + } else { + /* All others will be Hex escapes */ + + acpi_os_printf("\\x%2.2X", (s32) string[i]); + } + break; + } + } + acpi_os_printf("\""); + + if (i == max_length && string[i]) { + acpi_os_printf("..."); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_dword_byte_swap + * + * PARAMETERS: Value - Value to be converted + * + * RETURN: u32 integer with bytes swapped + * + * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes) + * + ******************************************************************************/ + +u32 acpi_ut_dword_byte_swap(u32 value) +{ + union { + u32 value; + u8 bytes[4]; + } out; + union { + u32 value; + u8 bytes[4]; + } in; + + ACPI_FUNCTION_ENTRY(); + + in.value = value; + + out.bytes[0] = in.bytes[3]; + out.bytes[1] = in.bytes[2]; + out.bytes[2] = in.bytes[1]; + out.bytes[3] = in.bytes[0]; + + return (out.value); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_set_integer_width + * + * PARAMETERS: Revision From DSDT header + * + * RETURN: None + * + * DESCRIPTION: Set the global integer bit width based upon the revision + * of the DSDT. For Revision 1 and 0, Integers are 32 bits. + * For Revision 2 and above, Integers are 64 bits. Yes, this + * makes a difference. + * + ******************************************************************************/ + +void acpi_ut_set_integer_width(u8 revision) +{ + + if (revision < 2) { + + /* 32-bit case */ + + acpi_gbl_integer_bit_width = 32; + acpi_gbl_integer_nybble_width = 8; + acpi_gbl_integer_byte_width = 4; + } else { + /* 64-bit case (ACPI 2.0+) */ + + acpi_gbl_integer_bit_width = 64; + acpi_gbl_integer_nybble_width = 16; + acpi_gbl_integer_byte_width = 8; + } +} + +#ifdef ACPI_DEBUG_OUTPUT +/******************************************************************************* + * + * FUNCTION: acpi_ut_display_init_pathname + * + * PARAMETERS: Type - Object type of the node + * obj_handle - Handle whose pathname will be displayed + * Path - Additional path string to be appended. + * (NULL if no extra path) + * + * RETURN: acpi_status + * + * DESCRIPTION: Display full pathname of an object, DEBUG ONLY + * + ******************************************************************************/ + +void +acpi_ut_display_init_pathname(u8 type, + struct acpi_namespace_node *obj_handle, + char *path) +{ + acpi_status status; + struct acpi_buffer buffer; + + ACPI_FUNCTION_ENTRY(); + + /* Only print the path if the appropriate debug level is enabled */ + + if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { + return; + } + + /* Get the full pathname to the node */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname(obj_handle, &buffer); + if (ACPI_FAILURE(status)) { + return; + } + + /* Print what we're doing */ + + switch (type) { + case ACPI_TYPE_METHOD: + acpi_os_printf("Executing "); + break; + + default: + acpi_os_printf("Initializing "); + break; + } + + /* Print the object type and pathname */ + + acpi_os_printf("%-12s %s", + acpi_ut_get_type_name(type), (char *)buffer.pointer); + + /* Extra path is used to append names like _STA, _INI, etc. */ + + if (path) { + acpi_os_printf(".%s", path); + } + acpi_os_printf("\n"); + + ACPI_FREE(buffer.pointer); +} +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_acpi_char + * + * PARAMETERS: Char - The character to be examined + * Position - Byte position (0-3) + * + * RETURN: TRUE if the character is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI character. Must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + * We allow a '!' as the last character because of the ASF! table + * + ******************************************************************************/ + +u8 acpi_ut_valid_acpi_char(char character, u32 position) +{ + + if (!((character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9') || (character == '_'))) { + + /* Allow a '!' in the last position */ + + if (character == '!' && position == 3) { + return (TRUE); + } + + return (FALSE); + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_acpi_name + * + * PARAMETERS: Name - The name to be examined + * + * RETURN: TRUE if the name is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + ******************************************************************************/ + +u8 acpi_ut_valid_acpi_name(u32 name) +{ + u32 i; + + ACPI_FUNCTION_ENTRY(); + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (!acpi_ut_valid_acpi_char + ((ACPI_CAST_PTR(char, &name))[i], i)) { + return (FALSE); + } + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_repair_name + * + * PARAMETERS: Name - The ACPI name to be repaired + * + * RETURN: Repaired version of the name + * + * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and + * return the new name. + * + ******************************************************************************/ + +acpi_name acpi_ut_repair_name(char *name) +{ + u32 i; + char new_name[ACPI_NAME_SIZE]; + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + new_name[i] = name[i]; + + /* + * Replace a bad character with something printable, yet technically + * still invalid. This prevents any collisions with existing "good" + * names in the namespace. + */ + if (!acpi_ut_valid_acpi_char(name[i], i)) { + new_name[i] = '*'; + } + } + + return (*(u32 *) new_name); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strtoul64 + * + * PARAMETERS: String - Null terminated string + * Base - Radix of the string: 16 or ACPI_ANY_BASE; + * ACPI_ANY_BASE means 'in behalf of to_integer' + * ret_integer - Where the converted integer is returned + * + * RETURN: Status and Converted value + * + * DESCRIPTION: Convert a string into an unsigned value. Performs either a + * 32-bit or 64-bit conversion, depending on the current mode + * of the interpreter. + * NOTE: Does not support Octal strings, not needed. + * + ******************************************************************************/ + +acpi_status +acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) +{ + u32 this_digit = 0; + acpi_integer return_value = 0; + acpi_integer quotient; + acpi_integer dividend; + u32 to_integer_op = (base == ACPI_ANY_BASE); + u32 mode32 = (acpi_gbl_integer_byte_width == 4); + u8 valid_digits = 0; + u8 sign_of0x = 0; + u8 term = 0; + + ACPI_FUNCTION_TRACE_STR(ut_stroul64, string); + + switch (base) { + case ACPI_ANY_BASE: + case 16: + break; + + default: + /* Invalid Base */ + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (!string) { + goto error_exit; + } + + /* Skip over any white space in the buffer */ + + while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { + string++; + } + + if (to_integer_op) { + /* + * Base equal to ACPI_ANY_BASE means 'to_integer operation case'. + * We need to determine if it is decimal or hexadecimal. + */ + if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { + sign_of0x = 1; + base = 16; + + /* Skip over the leading '0x' */ + string += 2; + } else { + base = 10; + } + } + + /* Any string left? Check that '0x' is not followed by white space. */ + + if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { + if (to_integer_op) { + goto error_exit; + } else { + goto all_done; + } + } + + /* + * Perform a 32-bit or 64-bit conversion, depending upon the current + * execution mode of the interpreter + */ + dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; + + /* Main loop: convert the string to a 32- or 64-bit integer */ + + while (*string) { + if (ACPI_IS_DIGIT(*string)) { + + /* Convert ASCII 0-9 to Decimal value */ + + this_digit = ((u8) * string) - '0'; + } else if (base == 10) { + + /* Digit is out of range; possible in to_integer case only */ + + term = 1; + } else { + this_digit = (u8) ACPI_TOUPPER(*string); + if (ACPI_IS_XDIGIT((char)this_digit)) { + + /* Convert ASCII Hex char to value */ + + this_digit = this_digit - 'A' + 10; + } else { + term = 1; + } + } + + if (term) { + if (to_integer_op) { + goto error_exit; + } else { + break; + } + } else if ((valid_digits == 0) && (this_digit == 0) + && !sign_of0x) { + + /* Skip zeros */ + string++; + continue; + } + + valid_digits++; + + if (sign_of0x && ((valid_digits > 16) + || ((valid_digits > 8) && mode32))) { + /* + * This is to_integer operation case. + * No any restrictions for string-to-integer conversion, + * see ACPI spec. + */ + goto error_exit; + } + + /* Divide the digit into the correct position */ + + (void) + acpi_ut_short_divide((dividend - (acpi_integer) this_digit), + base, "ient, NULL); + + if (return_value > quotient) { + if (to_integer_op) { + goto error_exit; + } else { + break; + } + } + + return_value *= base; + return_value += this_digit; + string++; + } + + /* All done, normal exit */ + + all_done: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(return_value))); + + *ret_integer = return_value; + return_ACPI_STATUS(AE_OK); + + error_exit: + /* Base was set/validated above */ + + if (base == 10) { + return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); + } else { + return_ACPI_STATUS(AE_BAD_HEX_CONSTANT); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_update_state_and_push + * + * PARAMETERS: Object - Object to be added to the new state + * Action - Increment/Decrement + * state_list - List the state will be added to + * + * RETURN: Status + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ + +acpi_status +acpi_ut_create_update_state_and_push(union acpi_operand_object *object, + u16 action, + union acpi_generic_state **state_list) +{ + union acpi_generic_state *state; + + ACPI_FUNCTION_ENTRY(); + + /* Ignore null objects; these are expected */ + + if (!object) { + return (AE_OK); + } + + state = acpi_ut_create_update_state(object, action); + if (!state) { + return (AE_NO_MEMORY); + } + + acpi_ut_push_generic_state(state_list, state); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_walk_package_tree + * + * PARAMETERS: source_object - The package to walk + * target_object - Target object (if package is being copied) + * walk_callback - Called once for each package element + * Context - Passed to the callback function + * + * RETURN: Status + * + * DESCRIPTION: Walk through a package + * + ******************************************************************************/ + +acpi_status +acpi_ut_walk_package_tree(union acpi_operand_object * source_object, + void *target_object, + acpi_pkg_callback walk_callback, void *context) +{ + acpi_status status = AE_OK; + union acpi_generic_state *state_list = NULL; + union acpi_generic_state *state; + u32 this_index; + union acpi_operand_object *this_source_obj; + + ACPI_FUNCTION_TRACE(ut_walk_package_tree); + + state = acpi_ut_create_pkg_state(source_object, target_object, 0); + if (!state) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + while (state) { + + /* Get one element of the package */ + + this_index = state->pkg.index; + this_source_obj = (union acpi_operand_object *) + state->pkg.source_object->package.elements[this_index]; + + /* + * Check for: + * 1) An uninitialized package element. It is completely + * legal to declare a package and leave it uninitialized + * 2) Not an internal object - can be a namespace node instead + * 3) Any type other than a package. Packages are handled in else + * case below. + */ + if ((!this_source_obj) || + (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) != + ACPI_DESC_TYPE_OPERAND) + || (ACPI_GET_OBJECT_TYPE(this_source_obj) != + ACPI_TYPE_PACKAGE)) { + status = + walk_callback(ACPI_COPY_TYPE_SIMPLE, + this_source_obj, state, context); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + state->pkg.index++; + while (state->pkg.index >= + state->pkg.source_object->package.count) { + /* + * We've handled all of the objects at this level, This means + * that we have just completed a package. That package may + * have contained one or more packages itself. + * + * Delete this state and pop the previous state (package). + */ + acpi_ut_delete_generic_state(state); + state = acpi_ut_pop_generic_state(&state_list); + + /* Finished when there are no more states */ + + if (!state) { + /* + * We have handled all of the objects in the top level + * package just add the length of the package objects + * and exit + */ + return_ACPI_STATUS(AE_OK); + } + + /* + * Go back up a level and move the index past the just + * completed package object. + */ + state->pkg.index++; + } + } else { + /* This is a subobject of type package */ + + status = + walk_callback(ACPI_COPY_TYPE_PACKAGE, + this_source_obj, state, context); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Push the current state and create a new one + * The callback above returned a new target package object. + */ + acpi_ut_push_generic_state(&state_list, state); + state = acpi_ut_create_pkg_state(this_source_obj, + state->pkg. + this_target_obj, 0); + if (!state) { + + /* Free any stacked Update State objects */ + + while (state_list) { + state = + acpi_ut_pop_generic_state + (&state_list); + acpi_ut_delete_generic_state(state); + } + return_ACPI_STATUS(AE_NO_MEMORY); + } + } + } + + /* We should never get here */ + + return_ACPI_STATUS(AE_AML_INTERNAL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_error, acpi_exception, acpi_warning, acpi_info + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print message with module/line/version info + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +acpi_error(const char *module_name, u32 line_number, const char *format, ...) +{ + va_list args; + + acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); + + va_start(args, format); + acpi_os_vprintf(format, args); + acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); + va_end(args); +} + +void ACPI_INTERNAL_VAR_XFACE +acpi_exception(const char *module_name, + u32 line_number, acpi_status status, const char *format, ...) +{ + va_list args; + + acpi_os_printf("ACPI Exception (%s-%04d): %s, ", module_name, + line_number, acpi_format_exception(status)); + + va_start(args, format); + acpi_os_vprintf(format, args); + acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); + va_end(args); +} + +void ACPI_INTERNAL_VAR_XFACE +acpi_warning(const char *module_name, u32 line_number, const char *format, ...) +{ + va_list args; + + acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number); + + va_start(args, format); + acpi_os_vprintf(format, args); + acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); + va_end(args); +} + +void ACPI_INTERNAL_VAR_XFACE +acpi_info(const char *module_name, u32 line_number, const char *format, ...) +{ + va_list args; + + /* + * Removed module_name, line_number, and acpica version, not needed + * for info output + */ + acpi_os_printf("ACPI: "); + + va_start(args, format); + acpi_os_vprintf(format, args); + acpi_os_printf("\n"); + va_end(args); +} + +ACPI_EXPORT_SYMBOL(acpi_error) +ACPI_EXPORT_SYMBOL(acpi_exception) +ACPI_EXPORT_SYMBOL(acpi_warning) +ACPI_EXPORT_SYMBOL(acpi_info) diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c new file mode 100644 index 000000000000..7b48ba3f3f8a --- /dev/null +++ b/drivers/acpi/acpica/utmutex.c @@ -0,0 +1,342 @@ +/******************************************************************************* + * + * Module Name: utmutex - local mutex support + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utmutex") + +/* Local prototypes */ +static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id); + +static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id); + +/******************************************************************************* + * + * FUNCTION: acpi_ut_mutex_initialize + * + * PARAMETERS: None. + * + * RETURN: Status + * + * DESCRIPTION: Create the system mutex objects. + * + ******************************************************************************/ + +acpi_status acpi_ut_mutex_initialize(void) +{ + u32 i; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_mutex_initialize); + + /* + * Create each of the predefined mutex objects + */ + for (i = 0; i < ACPI_NUM_MUTEX; i++) { + status = acpi_ut_create_mutex(i); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* Create the spinlocks for use at interrupt level */ + + spin_lock_init(acpi_gbl_gpe_lock); + spin_lock_init(acpi_gbl_hardware_lock); + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_mutex_terminate + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete all of the system mutex objects. + * + ******************************************************************************/ + +void acpi_ut_mutex_terminate(void) +{ + u32 i; + + ACPI_FUNCTION_TRACE(ut_mutex_terminate); + + /* + * Delete each predefined mutex object + */ + for (i = 0; i < ACPI_NUM_MUTEX; i++) { + (void)acpi_ut_delete_mutex(i); + } + + /* Delete the spinlocks */ + + acpi_os_delete_lock(acpi_gbl_gpe_lock); + acpi_os_delete_lock(acpi_gbl_hardware_lock); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_mutex + * + * PARAMETERS: mutex_iD - ID of the mutex to be created + * + * RETURN: Status + * + * DESCRIPTION: Create a mutex object. + * + ******************************************************************************/ + +static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id); + + if (mutex_id > ACPI_MAX_MUTEX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (!acpi_gbl_mutex_info[mutex_id].mutex) { + status = + acpi_os_create_mutex(&acpi_gbl_mutex_info[mutex_id].mutex); + acpi_gbl_mutex_info[mutex_id].thread_id = + ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[mutex_id].use_count = 0; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_delete_mutex + * + * PARAMETERS: mutex_iD - ID of the mutex to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Delete a mutex object. + * + ******************************************************************************/ + +static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id) +{ + + ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id); + + if (mutex_id > ACPI_MAX_MUTEX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + acpi_os_delete_mutex(acpi_gbl_mutex_info[mutex_id].mutex); + + acpi_gbl_mutex_info[mutex_id].mutex = NULL; + acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_acquire_mutex + * + * PARAMETERS: mutex_iD - ID of the mutex to be acquired + * + * RETURN: Status + * + * DESCRIPTION: Acquire a mutex object. + * + ******************************************************************************/ + +acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) +{ + acpi_status status; + acpi_thread_id this_thread_id; + + ACPI_FUNCTION_NAME(ut_acquire_mutex); + + if (mutex_id > ACPI_MAX_MUTEX) { + return (AE_BAD_PARAMETER); + } + + this_thread_id = acpi_os_get_thread_id(); + +#ifdef ACPI_MUTEX_DEBUG + { + u32 i; + /* + * Mutex debug code, for internal debugging only. + * + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than or equal to this one. If so, the thread has violated + * the mutex ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { + if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { + if (i == mutex_id) { + ACPI_ERROR((AE_INFO, + "Mutex [%s] already acquired by this thread [%X]", + acpi_ut_get_mutex_name + (mutex_id), + this_thread_id)); + + return (AE_ALREADY_ACQUIRED); + } + + ACPI_ERROR((AE_INFO, + "Invalid acquire order: Thread %X owns [%s], wants [%s]", + this_thread_id, + acpi_ut_get_mutex_name(i), + acpi_ut_get_mutex_name(mutex_id))); + + return (AE_ACQUIRE_DEADLOCK); + } + } + } +#endif + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "Thread %lX attempting to acquire Mutex [%s]\n", + (unsigned long)this_thread_id, + acpi_ut_get_mutex_name(mutex_id))); + + status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex, + ACPI_WAIT_FOREVER); + if (ACPI_SUCCESS(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "Thread %lX acquired Mutex [%s]\n", + (unsigned long)this_thread_id, + acpi_ut_get_mutex_name(mutex_id))); + + acpi_gbl_mutex_info[mutex_id].use_count++; + acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id; + } else { + ACPI_EXCEPTION((AE_INFO, status, + "Thread %lX could not acquire Mutex [%X]", + (unsigned long)this_thread_id, mutex_id)); + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_release_mutex + * + * PARAMETERS: mutex_iD - ID of the mutex to be released + * + * RETURN: Status + * + * DESCRIPTION: Release a mutex object. + * + ******************************************************************************/ + +acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) +{ + acpi_thread_id this_thread_id; + + ACPI_FUNCTION_NAME(ut_release_mutex); + + this_thread_id = acpi_os_get_thread_id(); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "Thread %lX releasing Mutex [%s]\n", + (unsigned long)this_thread_id, + acpi_ut_get_mutex_name(mutex_id))); + + if (mutex_id > ACPI_MAX_MUTEX) { + return (AE_BAD_PARAMETER); + } + + /* + * Mutex must be acquired in order to release it! + */ + if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) { + ACPI_ERROR((AE_INFO, + "Mutex [%X] is not acquired, cannot release", + mutex_id)); + + return (AE_NOT_ACQUIRED); + } +#ifdef ACPI_MUTEX_DEBUG + { + u32 i; + /* + * Mutex debug code, for internal debugging only. + * + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than this one. If so, the thread has violated the mutex + * ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { + if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { + if (i == mutex_id) { + continue; + } + + ACPI_ERROR((AE_INFO, + "Invalid release order: owns [%s], releasing [%s]", + acpi_ut_get_mutex_name(i), + acpi_ut_get_mutex_name(mutex_id))); + + return (AE_RELEASE_DEADLOCK); + } + } + } +#endif + + /* Mark unlocked FIRST */ + + acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; + + acpi_os_release_mutex(acpi_gbl_mutex_info[mutex_id].mutex); + return (AE_OK); +} diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c new file mode 100644 index 000000000000..964b23c11610 --- /dev/null +++ b/drivers/acpi/acpica/utobject.c @@ -0,0 +1,677 @@ +/****************************************************************************** + * + * Module Name: utobject - ACPI object create/delete/size/cache routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utobject") + +/* Local prototypes */ +static acpi_status +acpi_ut_get_simple_object_size(union acpi_operand_object *obj, + acpi_size * obj_length); + +static acpi_status +acpi_ut_get_package_object_size(union acpi_operand_object *obj, + acpi_size * obj_length); + +static acpi_status +acpi_ut_get_element_length(u8 object_type, + union acpi_operand_object *source_object, + union acpi_generic_state *state, void *context); + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_internal_object_dbg + * + * PARAMETERS: module_name - Source file name of caller + * line_number - Line number of caller + * component_id - Component type of caller + * Type - ACPI Type of the new object + * + * RETURN: A new internal object, null on failure + * + * DESCRIPTION: Create and initialize a new internal object. + * + * NOTE: We always allocate the worst-case object descriptor because + * these objects are cached, and we want them to be + * one-size-satisifies-any-request. This in itself may not be + * the most memory efficient, but the efficiency of the object + * cache should more than make up for this! + * + ******************************************************************************/ + +union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char + *module_name, + u32 line_number, + u32 component_id, + acpi_object_type + type) +{ + union acpi_operand_object *object; + union acpi_operand_object *second_object; + + ACPI_FUNCTION_TRACE_STR(ut_create_internal_object_dbg, + acpi_ut_get_type_name(type)); + + /* Allocate the raw object descriptor */ + + object = + acpi_ut_allocate_object_desc_dbg(module_name, line_number, + component_id); + if (!object) { + return_PTR(NULL); + } + + switch (type) { + case ACPI_TYPE_REGION: + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + + /* These types require a secondary object */ + + second_object = acpi_ut_allocate_object_desc_dbg(module_name, + line_number, + component_id); + if (!second_object) { + acpi_ut_delete_object_desc(object); + return_PTR(NULL); + } + + second_object->common.type = ACPI_TYPE_LOCAL_EXTRA; + second_object->common.reference_count = 1; + + /* Link the second object to the first */ + + object->common.next_object = second_object; + break; + + default: + /* All others have no secondary object */ + break; + } + + /* Save the object type in the object descriptor */ + + object->common.type = (u8) type; + + /* Init the reference count */ + + object->common.reference_count = 1; + + /* Any per-type initialization should go here */ + + return_PTR(object); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_package_object + * + * PARAMETERS: Count - Number of package elements + * + * RETURN: Pointer to a new Package object, null on failure + * + * DESCRIPTION: Create a fully initialized package object + * + ******************************************************************************/ + +union acpi_operand_object *acpi_ut_create_package_object(u32 count) +{ + union acpi_operand_object *package_desc; + union acpi_operand_object **package_elements; + + ACPI_FUNCTION_TRACE_U32(ut_create_package_object, count); + + /* Create a new Package object */ + + package_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE); + if (!package_desc) { + return_PTR(NULL); + } + + /* + * Create the element array. Count+1 allows the array to be null + * terminated. + */ + package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size) count + + 1) * sizeof(void *)); + if (!package_elements) { + acpi_ut_remove_reference(package_desc); + return_PTR(NULL); + } + + package_desc->package.count = count; + package_desc->package.elements = package_elements; + return_PTR(package_desc); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_buffer_object + * + * PARAMETERS: buffer_size - Size of buffer to be created + * + * RETURN: Pointer to a new Buffer object, null on failure + * + * DESCRIPTION: Create a fully initialized buffer object + * + ******************************************************************************/ + +union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size) +{ + union acpi_operand_object *buffer_desc; + u8 *buffer = NULL; + + ACPI_FUNCTION_TRACE_U32(ut_create_buffer_object, buffer_size); + + /* Create a new Buffer object */ + + buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); + if (!buffer_desc) { + return_PTR(NULL); + } + + /* Create an actual buffer only if size > 0 */ + + if (buffer_size > 0) { + + /* Allocate the actual buffer */ + + buffer = ACPI_ALLOCATE_ZEROED(buffer_size); + if (!buffer) { + ACPI_ERROR((AE_INFO, "Could not allocate size %X", + (u32) buffer_size)); + acpi_ut_remove_reference(buffer_desc); + return_PTR(NULL); + } + } + + /* Complete buffer object initialization */ + + buffer_desc->buffer.flags |= AOPOBJ_DATA_VALID; + buffer_desc->buffer.pointer = buffer; + buffer_desc->buffer.length = (u32) buffer_size; + + /* Return the new buffer descriptor */ + + return_PTR(buffer_desc); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_string_object + * + * PARAMETERS: string_size - Size of string to be created. Does not + * include NULL terminator, this is added + * automatically. + * + * RETURN: Pointer to a new String object + * + * DESCRIPTION: Create a fully initialized string object + * + ******************************************************************************/ + +union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size) +{ + union acpi_operand_object *string_desc; + char *string; + + ACPI_FUNCTION_TRACE_U32(ut_create_string_object, string_size); + + /* Create a new String object */ + + string_desc = acpi_ut_create_internal_object(ACPI_TYPE_STRING); + if (!string_desc) { + return_PTR(NULL); + } + + /* + * Allocate the actual string buffer -- (Size + 1) for NULL terminator. + * NOTE: Zero-length strings are NULL terminated + */ + string = ACPI_ALLOCATE_ZEROED(string_size + 1); + if (!string) { + ACPI_ERROR((AE_INFO, "Could not allocate size %X", + (u32) string_size)); + acpi_ut_remove_reference(string_desc); + return_PTR(NULL); + } + + /* Complete string object initialization */ + + string_desc->string.pointer = string; + string_desc->string.length = (u32) string_size; + + /* Return the new string descriptor */ + + return_PTR(string_desc); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_internal_object + * + * PARAMETERS: Object - Object to be validated + * + * RETURN: TRUE if object is valid, FALSE otherwise + * + * DESCRIPTION: Validate a pointer to be an union acpi_operand_object + * + ******************************************************************************/ + +u8 acpi_ut_valid_internal_object(void *object) +{ + + ACPI_FUNCTION_NAME(ut_valid_internal_object); + + /* Check for a null pointer */ + + if (!object) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Null Object Ptr\n")); + return (FALSE); + } + + /* Check the descriptor type field */ + + switch (ACPI_GET_DESCRIPTOR_TYPE(object)) { + case ACPI_DESC_TYPE_OPERAND: + + /* The object appears to be a valid union acpi_operand_object */ + + return (TRUE); + + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "%p is not not an ACPI operand obj [%s]\n", + object, acpi_ut_get_descriptor_name(object))); + break; + } + + return (FALSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate_object_desc_dbg + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * component_id - Caller's component ID (for error output) + * + * RETURN: Pointer to newly allocated object descriptor. Null on error + * + * DESCRIPTION: Allocate a new object descriptor. Gracefully handle + * error conditions. + * + ******************************************************************************/ + +void *acpi_ut_allocate_object_desc_dbg(const char *module_name, + u32 line_number, u32 component_id) +{ + union acpi_operand_object *object; + + ACPI_FUNCTION_TRACE(ut_allocate_object_desc_dbg); + + object = acpi_os_acquire_object(acpi_gbl_operand_cache); + if (!object) { + ACPI_ERROR((module_name, line_number, + "Could not allocate an object descriptor")); + + return_PTR(NULL); + } + + /* Mark the descriptor type */ + + memset(object, 0, sizeof(union acpi_operand_object)); + ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND); + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p Size %X\n", + object, (u32) sizeof(union acpi_operand_object))); + + return_PTR(object); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_delete_object_desc + * + * PARAMETERS: Object - An Acpi internal object to be deleted + * + * RETURN: None. + * + * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache + * + ******************************************************************************/ + +void acpi_ut_delete_object_desc(union acpi_operand_object *object) +{ + ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object); + + /* Object must be an union acpi_operand_object */ + + if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { + ACPI_ERROR((AE_INFO, + "%p is not an ACPI Operand object [%s]", object, + acpi_ut_get_descriptor_name(object))); + return_VOID; + } + + (void)acpi_os_release_object(acpi_gbl_operand_cache, object); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_simple_object_size + * + * PARAMETERS: internal_object - An ACPI operand object + * obj_length - Where the length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain a simple object for return to an external user. + * + * The length includes the object structure plus any additional + * needed space. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, + acpi_size * obj_length) +{ + acpi_size length; + acpi_size size; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object); + + /* + * Handle a null object (Could be a uninitialized package + * element -- which is legal) + */ + if (!internal_object) { + *obj_length = sizeof(union acpi_object); + return_ACPI_STATUS(AE_OK); + } + + /* Start with the length of the Acpi object */ + + length = sizeof(union acpi_object); + + if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) { + + /* Object is a named object (reference), just return the length */ + + *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); + return_ACPI_STATUS(status); + } + + /* + * The final length depends on the object type + * Strings and Buffers are packed right up against the parent object and + * must be accessed bytewise or there may be alignment problems on + * certain processors + */ + switch (ACPI_GET_OBJECT_TYPE(internal_object)) { + case ACPI_TYPE_STRING: + + length += (acpi_size) internal_object->string.length + 1; + break; + + case ACPI_TYPE_BUFFER: + + length += (acpi_size) internal_object->buffer.length; + break; + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + + /* No extra data for these types */ + + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + switch (internal_object->reference.class) { + case ACPI_REFCLASS_NAME: + + /* + * Get the actual length of the full pathname to this object. + * The reference will be converted to the pathname to the object + */ + size = + acpi_ns_get_pathname_length(internal_object-> + reference.node); + if (!size) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + length += ACPI_ROUND_UP_TO_NATIVE_WORD(size); + break; + + default: + + /* + * No other reference opcodes are supported. + * Notably, Locals and Args are not supported, but this may be + * required eventually. + */ + ACPI_ERROR((AE_INFO, + "Cannot convert to external object - " + "unsupported Reference Class [%s] %X in object %p", + acpi_ut_get_reference_name(internal_object), + internal_object->reference.class, + internal_object)); + status = AE_TYPE; + break; + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Cannot convert to external object - " + "unsupported type [%s] %X in object %p", + acpi_ut_get_object_type_name(internal_object), + ACPI_GET_OBJECT_TYPE(internal_object), + internal_object)); + status = AE_TYPE; + break; + } + + /* + * Account for the space required by the object rounded up to the next + * multiple of the machine word size. This keeps each object aligned + * on a machine word boundary. (preventing alignment faults on some + * machines.) + */ + *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_element_length + * + * PARAMETERS: acpi_pkg_callback + * + * RETURN: Status + * + * DESCRIPTION: Get the length of one package element. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_get_element_length(u8 object_type, + union acpi_operand_object *source_object, + union acpi_generic_state *state, void *context) +{ + acpi_status status = AE_OK; + struct acpi_pkg_info *info = (struct acpi_pkg_info *)context; + acpi_size object_space; + + switch (object_type) { + case ACPI_COPY_TYPE_SIMPLE: + + /* + * Simple object - just get the size (Null object/entry is handled + * here also) and sum it into the running package length + */ + status = + acpi_ut_get_simple_object_size(source_object, + &object_space); + if (ACPI_FAILURE(status)) { + return (status); + } + + info->length += object_space; + break; + + case ACPI_COPY_TYPE_PACKAGE: + + /* Package object - nothing much to do here, let the walk handle it */ + + info->num_packages++; + state->pkg.this_target_obj = NULL; + break; + + default: + + /* No other types allowed */ + + return (AE_BAD_PARAMETER); + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_package_object_size + * + * PARAMETERS: internal_object - An ACPI internal object + * obj_length - Where the length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain a package object for return to an external user. + * + * This is moderately complex since a package contains other + * objects including packages. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_get_package_object_size(union acpi_operand_object *internal_object, + acpi_size * obj_length) +{ + acpi_status status; + struct acpi_pkg_info info; + + ACPI_FUNCTION_TRACE_PTR(ut_get_package_object_size, internal_object); + + info.length = 0; + info.object_space = 0; + info.num_packages = 1; + + status = acpi_ut_walk_package_tree(internal_object, NULL, + acpi_ut_get_element_length, &info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * We have handled all of the objects in all levels of the package. + * just add the length of the package objects themselves. + * Round up to the next machine word. + */ + info.length += ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)) * + (acpi_size) info.num_packages; + + /* Return the total package length */ + + *obj_length = info.length; + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_object_size + * + * PARAMETERS: internal_object - An ACPI internal object + * obj_length - Where the length will be returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain an object for return to an API user. + * + ******************************************************************************/ + +acpi_status +acpi_ut_get_object_size(union acpi_operand_object *internal_object, + acpi_size * obj_length) +{ + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + if ((ACPI_GET_DESCRIPTOR_TYPE(internal_object) == + ACPI_DESC_TYPE_OPERAND) + && (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE)) { + status = + acpi_ut_get_package_object_size(internal_object, + obj_length); + } else { + status = + acpi_ut_get_simple_object_size(internal_object, obj_length); + } + + return (status); +} diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c new file mode 100644 index 000000000000..0755c5cdbe18 --- /dev/null +++ b/drivers/acpi/acpica/utresrc.c @@ -0,0 +1,616 @@ +/******************************************************************************* + * + * Module Name: utresrc - Resource management utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utresrc") +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) +/* + * Strings used to decode resource descriptors. + * Used by both the disasssembler and the debugger resource dump routines + */ +const char *acpi_gbl_bm_decode[] = { + "NotBusMaster", + "BusMaster" +}; + +const char *acpi_gbl_config_decode[] = { + "0 - Good Configuration", + "1 - Acceptable Configuration", + "2 - Suboptimal Configuration", + "3 - ***Invalid Configuration***", +}; + +const char *acpi_gbl_consume_decode[] = { + "ResourceProducer", + "ResourceConsumer" +}; + +const char *acpi_gbl_dec_decode[] = { + "PosDecode", + "SubDecode" +}; + +const char *acpi_gbl_he_decode[] = { + "Level", + "Edge" +}; + +const char *acpi_gbl_io_decode[] = { + "Decode10", + "Decode16" +}; + +const char *acpi_gbl_ll_decode[] = { + "ActiveHigh", + "ActiveLow" +}; + +const char *acpi_gbl_max_decode[] = { + "MaxNotFixed", + "MaxFixed" +}; + +const char *acpi_gbl_mem_decode[] = { + "NonCacheable", + "Cacheable", + "WriteCombining", + "Prefetchable" +}; + +const char *acpi_gbl_min_decode[] = { + "MinNotFixed", + "MinFixed" +}; + +const char *acpi_gbl_mtp_decode[] = { + "AddressRangeMemory", + "AddressRangeReserved", + "AddressRangeACPI", + "AddressRangeNVS" +}; + +const char *acpi_gbl_rng_decode[] = { + "InvalidRanges", + "NonISAOnlyRanges", + "ISAOnlyRanges", + "EntireRange" +}; + +const char *acpi_gbl_rw_decode[] = { + "ReadOnly", + "ReadWrite" +}; + +const char *acpi_gbl_shr_decode[] = { + "Exclusive", + "Shared" +}; + +const char *acpi_gbl_siz_decode[] = { + "Transfer8", + "Transfer8_16", + "Transfer16", + "InvalidSize" +}; + +const char *acpi_gbl_trs_decode[] = { + "DenseTranslation", + "SparseTranslation" +}; + +const char *acpi_gbl_ttp_decode[] = { + "TypeStatic", + "TypeTranslation" +}; + +const char *acpi_gbl_typ_decode[] = { + "Compatibility", + "TypeA", + "TypeB", + "TypeF" +}; + +#endif + +/* + * Base sizes of the raw AML resource descriptors, indexed by resource type. + * Zero indicates a reserved (and therefore invalid) resource type. + */ +const u8 acpi_gbl_resource_aml_sizes[] = { + /* Small descriptors */ + + 0, + 0, + 0, + 0, + ACPI_AML_SIZE_SMALL(struct aml_resource_irq), + ACPI_AML_SIZE_SMALL(struct aml_resource_dma), + ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent), + ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent), + ACPI_AML_SIZE_SMALL(struct aml_resource_io), + ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io), + 0, + 0, + 0, + 0, + ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small), + ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag), + + /* Large descriptors */ + + 0, + ACPI_AML_SIZE_LARGE(struct aml_resource_memory24), + ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register), + 0, + ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large), + ACPI_AML_SIZE_LARGE(struct aml_resource_memory32), + ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32), + ACPI_AML_SIZE_LARGE(struct aml_resource_address32), + ACPI_AML_SIZE_LARGE(struct aml_resource_address16), + ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq), + ACPI_AML_SIZE_LARGE(struct aml_resource_address64), + ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64) +}; + +/* + * Resource types, used to validate the resource length field. + * The length of fixed-length types must match exactly, variable + * lengths must meet the minimum required length, etc. + * Zero indicates a reserved (and therefore invalid) resource type. + */ +static const u8 acpi_gbl_resource_types[] = { + /* Small descriptors */ + + 0, + 0, + 0, + 0, + ACPI_SMALL_VARIABLE_LENGTH, + ACPI_FIXED_LENGTH, + ACPI_SMALL_VARIABLE_LENGTH, + ACPI_FIXED_LENGTH, + ACPI_FIXED_LENGTH, + ACPI_FIXED_LENGTH, + 0, + 0, + 0, + 0, + ACPI_VARIABLE_LENGTH, + ACPI_FIXED_LENGTH, + + /* Large descriptors */ + + 0, + ACPI_FIXED_LENGTH, + ACPI_FIXED_LENGTH, + 0, + ACPI_VARIABLE_LENGTH, + ACPI_FIXED_LENGTH, + ACPI_FIXED_LENGTH, + ACPI_VARIABLE_LENGTH, + ACPI_VARIABLE_LENGTH, + ACPI_VARIABLE_LENGTH, + ACPI_VARIABLE_LENGTH, + ACPI_FIXED_LENGTH +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_walk_aml_resources + * + * PARAMETERS: Aml - Pointer to the raw AML resource template + * aml_length - Length of the entire template + * user_function - Called once for each descriptor found. If + * NULL, a pointer to the end_tag is returned + * Context - Passed to user_function + * + * RETURN: Status + * + * DESCRIPTION: Walk a raw AML resource list(buffer). User function called + * once for each resource found. + * + ******************************************************************************/ + +acpi_status +acpi_ut_walk_aml_resources(u8 * aml, + acpi_size aml_length, + acpi_walk_aml_callback user_function, void **context) +{ + acpi_status status; + u8 *end_aml; + u8 resource_index; + u32 length; + u32 offset = 0; + + ACPI_FUNCTION_TRACE(ut_walk_aml_resources); + + /* The absolute minimum resource template is one end_tag descriptor */ + + if (aml_length < sizeof(struct aml_resource_end_tag)) { + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + } + + /* Point to the end of the resource template buffer */ + + end_aml = aml + aml_length; + + /* Walk the byte list, abort on any invalid descriptor type or length */ + + while (aml < end_aml) { + + /* Validate the Resource Type and Resource Length */ + + status = acpi_ut_validate_resource(aml, &resource_index); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the length of this descriptor */ + + length = acpi_ut_get_descriptor_length(aml); + + /* Invoke the user function */ + + if (user_function) { + status = + user_function(aml, length, offset, resource_index, + context); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + /* An end_tag descriptor terminates this resource template */ + + if (acpi_ut_get_resource_type(aml) == + ACPI_RESOURCE_NAME_END_TAG) { + /* + * There must be at least one more byte in the buffer for + * the 2nd byte of the end_tag + */ + if ((aml + 1) >= end_aml) { + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + } + + /* Return the pointer to the end_tag if requested */ + + if (!user_function) { + *context = aml; + } + + /* Normal exit */ + + return_ACPI_STATUS(AE_OK); + } + + aml += length; + offset += length; + } + + /* Did not find an end_tag descriptor */ + + return (AE_AML_NO_RESOURCE_END_TAG); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_validate_resource + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * return_index - Where the resource index is returned. NULL + * if the index is not required. + * + * RETURN: Status, and optionally the Index into the global resource tables + * + * DESCRIPTION: Validate an AML resource descriptor by checking the Resource + * Type and Resource Length. Returns an index into the global + * resource information/dispatch tables for later use. + * + ******************************************************************************/ + +acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) +{ + u8 resource_type; + u8 resource_index; + acpi_rs_length resource_length; + acpi_rs_length minimum_resource_length; + + ACPI_FUNCTION_ENTRY(); + + /* + * 1) Validate the resource_type field (Byte 0) + */ + resource_type = ACPI_GET8(aml); + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (resource_type & ACPI_RESOURCE_NAME_LARGE) { + + /* Verify the large resource type (name) against the max */ + + if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) { + return (AE_AML_INVALID_RESOURCE_TYPE); + } + + /* + * Large Resource Type -- bits 6:0 contain the name + * Translate range 0x80-0x8B to index range 0x10-0x1B + */ + resource_index = (u8) (resource_type - 0x70); + } else { + /* + * Small Resource Type -- bits 6:3 contain the name + * Shift range to index range 0x00-0x0F + */ + resource_index = (u8) + ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); + } + + /* Check validity of the resource type, zero indicates name is invalid */ + + if (!acpi_gbl_resource_types[resource_index]) { + return (AE_AML_INVALID_RESOURCE_TYPE); + } + + /* + * 2) Validate the resource_length field. This ensures that the length + * is at least reasonable, and guarantees that it is non-zero. + */ + resource_length = acpi_ut_get_resource_length(aml); + minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index]; + + /* Validate based upon the type of resource - fixed length or variable */ + + switch (acpi_gbl_resource_types[resource_index]) { + case ACPI_FIXED_LENGTH: + + /* Fixed length resource, length must match exactly */ + + if (resource_length != minimum_resource_length) { + return (AE_AML_BAD_RESOURCE_LENGTH); + } + break; + + case ACPI_VARIABLE_LENGTH: + + /* Variable length resource, length must be at least the minimum */ + + if (resource_length < minimum_resource_length) { + return (AE_AML_BAD_RESOURCE_LENGTH); + } + break; + + case ACPI_SMALL_VARIABLE_LENGTH: + + /* Small variable length resource, length can be (Min) or (Min-1) */ + + if ((resource_length > minimum_resource_length) || + (resource_length < (minimum_resource_length - 1))) { + return (AE_AML_BAD_RESOURCE_LENGTH); + } + break; + + default: + + /* Shouldn't happen (because of validation earlier), but be sure */ + + return (AE_AML_INVALID_RESOURCE_TYPE); + } + + /* Optionally return the resource table index */ + + if (return_index) { + *return_index = resource_index; + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_resource_type + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: The Resource Type with no extraneous bits (except the + * Large/Small descriptor bit -- this is left alone) + * + * DESCRIPTION: Extract the Resource Type/Name from the first byte of + * a resource descriptor. + * + ******************************************************************************/ + +u8 acpi_ut_get_resource_type(void *aml) +{ + ACPI_FUNCTION_ENTRY(); + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { + + /* Large Resource Type -- bits 6:0 contain the name */ + + return (ACPI_GET8(aml)); + } else { + /* Small Resource Type -- bits 6:3 contain the name */ + + return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_resource_length + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Byte Length + * + * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By + * definition, this does not include the size of the descriptor + * header or the length field itself. + * + ******************************************************************************/ + +u16 acpi_ut_get_resource_length(void *aml) +{ + acpi_rs_length resource_length; + + ACPI_FUNCTION_ENTRY(); + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { + + /* Large Resource type -- bytes 1-2 contain the 16-bit length */ + + ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1)); + + } else { + /* Small Resource type -- bits 2:0 of byte 0 contain the length */ + + resource_length = (u16) (ACPI_GET8(aml) & + ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); + } + + return (resource_length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_resource_header_length + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Length of the AML header (depends on large/small descriptor) + * + * DESCRIPTION: Get the length of the header for this resource. + * + ******************************************************************************/ + +u8 acpi_ut_get_resource_header_length(void *aml) +{ + ACPI_FUNCTION_ENTRY(); + + /* Examine the large/small bit in the resource header */ + + if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { + return (sizeof(struct aml_resource_large_header)); + } else { + return (sizeof(struct aml_resource_small_header)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_descriptor_length + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Byte length + * + * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the + * length of the descriptor header and the length field itself. + * Used to walk descriptor lists. + * + ******************************************************************************/ + +u32 acpi_ut_get_descriptor_length(void *aml) +{ + ACPI_FUNCTION_ENTRY(); + + /* + * Get the Resource Length (does not include header length) and add + * the header length (depends on if this is a small or large resource) + */ + return (acpi_ut_get_resource_length(aml) + + acpi_ut_get_resource_header_length(aml)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_resource_end_tag + * + * PARAMETERS: obj_desc - The resource template buffer object + * end_tag - Where the pointer to the end_tag is returned + * + * RETURN: Status, pointer to the end tag + * + * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template + * Note: allows a buffer length of zero. + * + ******************************************************************************/ + +acpi_status +acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, + u8 ** end_tag) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_get_resource_end_tag); + + /* Allow a buffer length of zero */ + + if (!obj_desc->buffer.length) { + *end_tag = obj_desc->buffer.pointer; + return_ACPI_STATUS(AE_OK); + } + + /* Validate the template and get a pointer to the end_tag */ + + status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer, + obj_desc->buffer.length, NULL, + (void **)end_tag); + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c new file mode 100644 index 000000000000..54c3461e2f26 --- /dev/null +++ b/drivers/acpi/acpica/utstate.c @@ -0,0 +1,347 @@ +/******************************************************************************* + * + * Module Name: utstate - state object support procedures + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utstate") + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_pkg_state_and_push + * + * PARAMETERS: Object - Object to be added to the new state + * Action - Increment/Decrement + * state_list - List the state will be added to + * + * RETURN: Status + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ +acpi_status +acpi_ut_create_pkg_state_and_push(void *internal_object, + void *external_object, + u16 index, + union acpi_generic_state **state_list) +{ + union acpi_generic_state *state; + + ACPI_FUNCTION_ENTRY(); + + state = + acpi_ut_create_pkg_state(internal_object, external_object, index); + if (!state) { + return (AE_NO_MEMORY); + } + + acpi_ut_push_generic_state(state_list, state); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_push_generic_state + * + * PARAMETERS: list_head - Head of the state stack + * State - State object to push + * + * RETURN: None + * + * DESCRIPTION: Push a state object onto a state stack + * + ******************************************************************************/ + +void +acpi_ut_push_generic_state(union acpi_generic_state **list_head, + union acpi_generic_state *state) +{ + ACPI_FUNCTION_TRACE(ut_push_generic_state); + + /* Push the state object onto the front of the list (stack) */ + + state->common.next = *list_head; + *list_head = state; + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_pop_generic_state + * + * PARAMETERS: list_head - Head of the state stack + * + * RETURN: The popped state object + * + * DESCRIPTION: Pop a state object from a state stack + * + ******************************************************************************/ + +union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state + **list_head) +{ + union acpi_generic_state *state; + + ACPI_FUNCTION_TRACE(ut_pop_generic_state); + + /* Remove the state object at the head of the list (stack) */ + + state = *list_head; + if (state) { + + /* Update the list head */ + + *list_head = state->common.next; + } + + return_PTR(state); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_generic_state + * + * PARAMETERS: None + * + * RETURN: The new state object. NULL on failure. + * + * DESCRIPTION: Create a generic state object. Attempt to obtain one from + * the global state cache; If none available, create a new one. + * + ******************************************************************************/ + +union acpi_generic_state *acpi_ut_create_generic_state(void) +{ + union acpi_generic_state *state; + + ACPI_FUNCTION_ENTRY(); + + state = acpi_os_acquire_object(acpi_gbl_state_cache); + if (state) { + + /* Initialize */ + memset(state, 0, sizeof(union acpi_generic_state)); + state->common.descriptor_type = ACPI_DESC_TYPE_STATE; + } + + return (state); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_thread_state + * + * PARAMETERS: None + * + * RETURN: New Thread State. NULL on failure + * + * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used + * to track per-thread info during method execution + * + ******************************************************************************/ + +struct acpi_thread_state *acpi_ut_create_thread_state(void) +{ + union acpi_generic_state *state; + + ACPI_FUNCTION_TRACE(ut_create_thread_state); + + /* Create the generic state object */ + + state = acpi_ut_create_generic_state(); + if (!state) { + return_PTR(NULL); + } + + /* Init fields specific to the update struct */ + + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_THREAD; + state->thread.thread_id = acpi_os_get_thread_id(); + + /* Check for invalid thread ID - zero is very bad, it will break things */ + + if (!state->thread.thread_id) { + ACPI_ERROR((AE_INFO, "Invalid zero ID from AcpiOsGetThreadId")); + state->thread.thread_id = (acpi_thread_id) 1; + } + + return_PTR((struct acpi_thread_state *)state); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_update_state + * + * PARAMETERS: Object - Initial Object to be installed in the state + * Action - Update action to be performed + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create an "Update State" - a flavor of the generic state used + * to update reference counts and delete complex objects such + * as packages. + * + ******************************************************************************/ + +union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object + *object, u16 action) +{ + union acpi_generic_state *state; + + ACPI_FUNCTION_TRACE_PTR(ut_create_update_state, object); + + /* Create the generic state object */ + + state = acpi_ut_create_generic_state(); + if (!state) { + return_PTR(NULL); + } + + /* Init fields specific to the update struct */ + + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_UPDATE; + state->update.object = object; + state->update.value = action; + + return_PTR(state); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_pkg_state + * + * PARAMETERS: Object - Initial Object to be installed in the state + * Action - Update action to be performed + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create a "Package State" + * + ******************************************************************************/ + +union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, + void *external_object, + u16 index) +{ + union acpi_generic_state *state; + + ACPI_FUNCTION_TRACE_PTR(ut_create_pkg_state, internal_object); + + /* Create the generic state object */ + + state = acpi_ut_create_generic_state(); + if (!state) { + return_PTR(NULL); + } + + /* Init fields specific to the update struct */ + + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_PACKAGE; + state->pkg.source_object = (union acpi_operand_object *)internal_object; + state->pkg.dest_object = external_object; + state->pkg.index = index; + state->pkg.num_packages = 1; + + return_PTR(state); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_control_state + * + * PARAMETERS: None + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create a "Control State" - a flavor of the generic state used + * to support nested IF/WHILE constructs in the AML. + * + ******************************************************************************/ + +union acpi_generic_state *acpi_ut_create_control_state(void) +{ + union acpi_generic_state *state; + + ACPI_FUNCTION_TRACE(ut_create_control_state); + + /* Create the generic state object */ + + state = acpi_ut_create_generic_state(); + if (!state) { + return_PTR(NULL); + } + + /* Init fields specific to the control struct */ + + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL; + state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING; + + return_PTR(state); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_delete_generic_state + * + * PARAMETERS: State - The state object to be deleted + * + * RETURN: None + * + * DESCRIPTION: Release a state object to the state cache. NULL state objects + * are ignored. + * + ******************************************************************************/ + +void acpi_ut_delete_generic_state(union acpi_generic_state *state) +{ + ACPI_FUNCTION_TRACE(ut_delete_generic_state); + + /* Ignore null state */ + + if (state) { + (void)acpi_os_release_object(acpi_gbl_state_cache, state); + } + return_VOID; +} diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c new file mode 100644 index 000000000000..5b27724a2749 --- /dev/null +++ b/drivers/acpi/acpica/utxface.c @@ -0,0 +1,512 @@ +/****************************************************************************** + * + * Module Name: utxface - External interfaces for "global" ACPI functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2008, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utxface") + +#ifndef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: acpi_initialize_subsystem + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initializes all global variables. This is the first function + * called, so any early initialization belongs here. + * + ******************************************************************************/ +acpi_status __init acpi_initialize_subsystem(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_initialize_subsystem); + + acpi_gbl_startup_flags = ACPI_SUBSYSTEM_INITIALIZE; + ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace()); + + /* Initialize the OS-Dependent layer */ + + status = acpi_os_initialize(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization")); + return_ACPI_STATUS(status); + } + + /* Initialize all globals used by the subsystem */ + + status = acpi_ut_init_globals(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During initialization of globals")); + return_ACPI_STATUS(status); + } + + /* Create the default mutex objects */ + + status = acpi_ut_mutex_initialize(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During Global Mutex creation")); + return_ACPI_STATUS(status); + } + + /* + * Initialize the namespace manager and + * the root of the namespace tree + */ + status = acpi_ns_root_initialize(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During Namespace initialization")); + return_ACPI_STATUS(status); + } + + /* If configured, initialize the AML debugger */ + + ACPI_DEBUGGER_EXEC(status = acpi_db_initialize()); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_enable_subsystem + * + * PARAMETERS: Flags - Init/enable Options + * + * RETURN: Status + * + * DESCRIPTION: Completes the subsystem initialization including hardware. + * Puts system into ACPI mode if it isn't already. + * + ******************************************************************************/ +acpi_status acpi_enable_subsystem(u32 flags) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(acpi_enable_subsystem); + + /* Enable ACPI mode */ + + if (!(flags & ACPI_NO_ACPI_ENABLE)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Going into ACPI mode\n")); + + acpi_gbl_original_mode = acpi_hw_get_mode(); + + status = acpi_enable(); + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, "AcpiEnable failed")); + return_ACPI_STATUS(status); + } + } + + /* + * Obtain a permanent mapping for the FACS. This is required for the + * Global Lock and the Firmware Waking Vector + */ + status = acpi_tb_initialize_facs(); + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, "Could not map the FACS table")); + return_ACPI_STATUS(status); + } + + /* + * Install the default op_region handlers. These are installed unless + * other handlers have already been installed via the + * install_address_space_handler interface. + */ + if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Installing default address space handlers\n")); + + status = acpi_ev_install_region_handlers(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * Initialize ACPI Event handling (Fixed and General Purpose) + * + * Note1: We must have the hardware and events initialized before we can + * execute any control methods safely. Any control method can require + * ACPI hardware support, so the hardware must be fully initialized before + * any method execution! + * + * Note2: Fixed events are initialized and enabled here. GPEs are + * initialized, but cannot be enabled until after the hardware is + * completely initialized (SCI and global_lock activated) + */ + if (!(flags & ACPI_NO_EVENT_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Initializing ACPI events\n")); + + status = acpi_ev_initialize_events(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * Install the SCI handler and Global Lock handler. This completes the + * hardware initialization. + */ + if (!(flags & ACPI_NO_HANDLER_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Installing SCI/GL handlers\n")); + + status = acpi_ev_install_xrupt_handlers(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_enable_subsystem) + +/******************************************************************************* + * + * FUNCTION: acpi_initialize_objects + * + * PARAMETERS: Flags - Init/enable Options + * + * RETURN: Status + * + * DESCRIPTION: Completes namespace initialization by initializing device + * objects and executing AML code for Regions, buffers, etc. + * + ******************************************************************************/ +acpi_status acpi_initialize_objects(u32 flags) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(acpi_initialize_objects); + + /* + * Run all _REG methods + * + * Note: Any objects accessed by the _REG methods will be automatically + * initialized, even if they contain executable AML (see the call to + * acpi_ns_initialize_objects below). + */ + if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Executing _REG OpRegion methods\n")); + + status = acpi_ev_initialize_op_regions(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * Initialize the objects that remain uninitialized. This runs the + * executable AML that may be part of the declaration of these objects: + * operation_regions, buffer_fields, Buffers, and Packages. + */ + if (!(flags & ACPI_NO_OBJECT_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Completing Initialization of ACPI Objects\n")); + + status = acpi_ns_initialize_objects(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * Initialize all device objects in the namespace. This runs the device + * _STA and _INI methods. + */ + if (!(flags & ACPI_NO_DEVICE_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Initializing ACPI Devices\n")); + + status = acpi_ns_initialize_devices(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * Complete the GPE initialization for the GPE blocks defined in the FADT + * (GPE block 0 and 1). + * + * Note1: This is where the _PRW methods are executed for the GPEs. These + * methods can only be executed after the SCI and Global Lock handlers are + * installed and initialized. + * + * Note2: Currently, there seems to be no need to run the _REG methods + * before execution of the _PRW methods and enabling of the GPEs. + */ + if (!(flags & ACPI_NO_EVENT_INIT)) { + status = acpi_ev_install_fadt_gpes(); + if (ACPI_FAILURE(status)) + return (status); + } + + /* + * Empty the caches (delete the cached objects) on the assumption that + * the table load filled them up more than they will be at runtime -- + * thus wasting non-paged memory. + */ + status = acpi_purge_cached_objects(); + + acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK; + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_initialize_objects) + +#endif +/******************************************************************************* + * + * FUNCTION: acpi_terminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Shutdown the ACPI subsystem. Release all resources. + * + ******************************************************************************/ +acpi_status acpi_terminate(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_terminate); + + /* Terminate the AML Debugger if present */ + + ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE); + + /* Shutdown and free all resources */ + + acpi_ut_subsystem_shutdown(); + + /* Free the mutex objects */ + + acpi_ut_mutex_terminate(); + +#ifdef ACPI_DEBUGGER + + /* Shut down the debugger */ + + acpi_db_terminate(); +#endif + + /* Now we can shutdown the OS-dependent layer */ + + status = acpi_os_terminate(); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_terminate) +#ifndef ACPI_ASL_COMPILER +#ifdef ACPI_FUTURE_USAGE +/******************************************************************************* + * + * FUNCTION: acpi_subsystem_status + * + * PARAMETERS: None + * + * RETURN: Status of the ACPI subsystem + * + * DESCRIPTION: Other drivers that use the ACPI subsystem should call this + * before making any other calls, to ensure the subsystem + * initialized successfully. + * + ******************************************************************************/ +acpi_status acpi_subsystem_status(void) +{ + + if (acpi_gbl_startup_flags & ACPI_INITIALIZED_OK) { + return (AE_OK); + } else { + return (AE_ERROR); + } +} + +ACPI_EXPORT_SYMBOL(acpi_subsystem_status) + +/******************************************************************************* + * + * FUNCTION: acpi_get_system_info + * + * PARAMETERS: out_buffer - A buffer to receive the resources for the + * device + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get information about the current + * state of the ACPI subsystem. It will return system information + * in the out_buffer. + * + * If the function fails an appropriate status will be returned + * and the value of out_buffer is undefined. + * + ******************************************************************************/ +acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) +{ + struct acpi_system_info *info_ptr; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_get_system_info); + + /* Parameter validation */ + + status = acpi_ut_validate_buffer(out_buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Validate/Allocate/Clear caller buffer */ + + status = + acpi_ut_initialize_buffer(out_buffer, + sizeof(struct acpi_system_info)); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Populate the return buffer + */ + info_ptr = (struct acpi_system_info *)out_buffer->pointer; + + info_ptr->acpi_ca_version = ACPI_CA_VERSION; + + /* System flags (ACPI capabilities) */ + + info_ptr->flags = ACPI_SYS_MODE_ACPI; + + /* Timer resolution - 24 or 32 bits */ + + if (acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) { + info_ptr->timer_resolution = 24; + } else { + info_ptr->timer_resolution = 32; + } + + /* Clear the reserved fields */ + + info_ptr->reserved1 = 0; + info_ptr->reserved2 = 0; + + /* Current debug levels */ + + info_ptr->debug_layer = acpi_dbg_layer; + info_ptr->debug_level = acpi_dbg_level; + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_get_system_info) + +/***************************************************************************** + * + * FUNCTION: acpi_install_initialization_handler + * + * PARAMETERS: Handler - Callback procedure + * Function - Not (currently) used, see below + * + * RETURN: Status + * + * DESCRIPTION: Install an initialization handler + * + * TBD: When a second function is added, must save the Function also. + * + ****************************************************************************/ +acpi_status +acpi_install_initialization_handler(acpi_init_handler handler, u32 function) +{ + + if (!handler) { + return (AE_BAD_PARAMETER); + } + + if (acpi_gbl_init_handler) { + return (AE_ALREADY_EXISTS); + } + + acpi_gbl_init_handler = handler; + return AE_OK; +} + +ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) +#endif /* ACPI_FUTURE_USAGE */ +/***************************************************************************** + * + * FUNCTION: acpi_purge_cached_objects + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Empty all caches (delete the cached objects) + * + ****************************************************************************/ +acpi_status acpi_purge_cached_objects(void) +{ + ACPI_FUNCTION_TRACE(acpi_purge_cached_objects); + + (void)acpi_os_purge_cache(acpi_gbl_state_cache); + (void)acpi_os_purge_cache(acpi_gbl_operand_cache); + (void)acpi_os_purge_cache(acpi_gbl_ps_node_cache); + (void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache); + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) +#endif diff --git a/drivers/acpi/dispatcher/Makefile b/drivers/acpi/dispatcher/Makefile deleted file mode 100644 index eb7e602a83cd..000000000000 --- a/drivers/acpi/dispatcher/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -obj-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \ - dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \ - dsinit.o - -EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c deleted file mode 100644 index 5fbc24075b44..000000000000 --- a/drivers/acpi/dispatcher/dsfield.c +++ /dev/null @@ -1,650 +0,0 @@ -/****************************************************************************** - * - * Module Name: dsfield - Dispatcher field routines - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_DISPATCHER -ACPI_MODULE_NAME("dsfield") - -/* Local prototypes */ -static acpi_status -acpi_ds_get_field_names(struct acpi_create_field_info *info, - struct acpi_walk_state *walk_state, - union acpi_parse_object *arg); - -/******************************************************************************* - * - * FUNCTION: acpi_ds_create_buffer_field - * - * PARAMETERS: Op - Current parse op (create_xXField) - * walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Execute the create_field operators: - * create_bit_field_op, - * create_byte_field_op, - * create_word_field_op, - * create_dword_field_op, - * create_qword_field_op, - * create_field_op (all of which define a field in a buffer) - * - ******************************************************************************/ - -acpi_status -acpi_ds_create_buffer_field(union acpi_parse_object *op, - struct acpi_walk_state *walk_state) -{ - union acpi_parse_object *arg; - struct acpi_namespace_node *node; - acpi_status status; - union acpi_operand_object *obj_desc; - union acpi_operand_object *second_desc = NULL; - u32 flags; - - ACPI_FUNCTION_TRACE(ds_create_buffer_field); - - /* - * Get the name_string argument (name of the new buffer_field) - */ - if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { - - /* For create_field, name is the 4th argument */ - - arg = acpi_ps_get_arg(op, 3); - } else { - /* For all other create_xXXField operators, name is the 3rd argument */ - - arg = acpi_ps_get_arg(op, 2); - } - - if (!arg) { - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - if (walk_state->deferred_node) { - node = walk_state->deferred_node; - status = AE_OK; - } else { - /* Execute flag should always be set when this function is entered */ - - if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - /* Creating new namespace node, should not already exist */ - - flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | - ACPI_NS_ERROR_IF_FOUND; - - /* Mark node temporary if we are executing a method */ - - if (walk_state->method_node) { - flags |= ACPI_NS_TEMPORARY; - } - - /* Enter the name_string into the namespace */ - - status = - acpi_ns_lookup(walk_state->scope_info, - arg->common.value.string, ACPI_TYPE_ANY, - ACPI_IMODE_LOAD_PASS1, flags, walk_state, - &node); - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.string, status); - return_ACPI_STATUS(status); - } - } - - /* - * We could put the returned object (Node) on the object stack for later, - * but for now, we will put it in the "op" object that the parser uses, - * so we can get it again at the end of this scope. - */ - op->common.node = node; - - /* - * If there is no object attached to the node, this node was just created - * and we need to create the field object. Otherwise, this was a lookup - * of an existing node and we don't want to create the field object again. - */ - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - return_ACPI_STATUS(AE_OK); - } - - /* - * The Field definition is not fully parsed at this time. - * (We must save the address of the AML for the buffer and index operands) - */ - - /* Create the buffer field object */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * Remember location in AML stream of the field unit opcode and operands -- - * since the buffer and index operands must be evaluated. - */ - second_desc = obj_desc->common.next_object; - second_desc->extra.aml_start = op->named.data; - second_desc->extra.aml_length = op->named.length; - obj_desc->buffer_field.node = node; - - /* Attach constructed field descriptors to parent node */ - - status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - cleanup: - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_field_names - * - * PARAMETERS: Info - create_field info structure - * ` walk_state - Current method state - * Arg - First parser arg for the field name list - * - * RETURN: Status - * - * DESCRIPTION: Process all named fields in a field declaration. Names are - * entered into the namespace. - * - ******************************************************************************/ - -static acpi_status -acpi_ds_get_field_names(struct acpi_create_field_info *info, - struct acpi_walk_state *walk_state, - union acpi_parse_object *arg) -{ - acpi_status status; - acpi_integer position; - - ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); - - /* First field starts at bit zero */ - - info->field_bit_position = 0; - - /* Process all elements in the field list (of parse nodes) */ - - while (arg) { - /* - * Three types of field elements are handled: - * 1) Offset - specifies a bit offset - * 2) access_as - changes the access mode - * 3) Name - Enters a new named field into the namespace - */ - switch (arg->common.aml_opcode) { - case AML_INT_RESERVEDFIELD_OP: - - position = (acpi_integer) info->field_bit_position - + (acpi_integer) arg->common.value.size; - - if (position > ACPI_UINT32_MAX) { - ACPI_ERROR((AE_INFO, - "Bit offset within field too large (> 0xFFFFFFFF)")); - return_ACPI_STATUS(AE_SUPPORT); - } - - info->field_bit_position = (u32) position; - break; - - case AML_INT_ACCESSFIELD_OP: - - /* - * Get a new access_type and access_attribute -- to be used for all - * field units that follow, until field end or another access_as - * keyword. - * - * In field_flags, preserve the flag bits other than the - * ACCESS_TYPE bits - */ - info->field_flags = (u8) - ((info-> - field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | - ((u8) ((u32) arg->common.value.integer >> 8))); - - info->attribute = (u8) (arg->common.value.integer); - break; - - case AML_INT_NAMEDFIELD_OP: - - /* Lookup the name, it should already exist */ - - status = acpi_ns_lookup(walk_state->scope_info, - (char *)&arg->named.name, - info->field_type, - ACPI_IMODE_EXECUTE, - ACPI_NS_DONT_OPEN_SCOPE, - walk_state, &info->field_node); - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE((char *)&arg->named.name, - status); - return_ACPI_STATUS(status); - } else { - arg->common.node = info->field_node; - info->field_bit_length = arg->common.value.size; - - /* - * If there is no object attached to the node, this node was - * just created and we need to create the field object. - * Otherwise, this was a lookup of an existing node and we - * don't want to create the field object again. - */ - if (!acpi_ns_get_attached_object - (info->field_node)) { - status = acpi_ex_prep_field_value(info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - } - - /* Keep track of bit position for the next field */ - - position = (acpi_integer) info->field_bit_position - + (acpi_integer) arg->common.value.size; - - if (position > ACPI_UINT32_MAX) { - ACPI_ERROR((AE_INFO, - "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)", - ACPI_CAST_PTR(char, - &info->field_node-> - name))); - return_ACPI_STATUS(AE_SUPPORT); - } - - info->field_bit_position += info->field_bit_length; - break; - - default: - - ACPI_ERROR((AE_INFO, - "Invalid opcode in field list: %X", - arg->common.aml_opcode)); - return_ACPI_STATUS(AE_AML_BAD_OPCODE); - } - - arg = arg->common.next; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_create_field - * - * PARAMETERS: Op - Op containing the Field definition and args - * region_node - Object for the containing Operation Region - * ` walk_state - Current method state - * - * RETURN: Status - * - * DESCRIPTION: Create a new field in the specified operation region - * - ******************************************************************************/ - -acpi_status -acpi_ds_create_field(union acpi_parse_object *op, - struct acpi_namespace_node *region_node, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_parse_object *arg; - struct acpi_create_field_info info; - - ACPI_FUNCTION_TRACE_PTR(ds_create_field, op); - - /* First arg is the name of the parent op_region (must already exist) */ - - arg = op->common.value.arg; - if (!region_node) { - status = - acpi_ns_lookup(walk_state->scope_info, - arg->common.value.name, ACPI_TYPE_REGION, - ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, - walk_state, ®ion_node); - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.name, status); - return_ACPI_STATUS(status); - } - } - - /* Second arg is the field flags */ - - arg = arg->common.next; - info.field_flags = (u8) arg->common.value.integer; - info.attribute = 0; - - /* Each remaining arg is a Named Field */ - - info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD; - info.region_node = region_node; - - status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_init_field_objects - * - * PARAMETERS: Op - Op containing the Field definition and args - * ` walk_state - Current method state - * - * RETURN: Status - * - * DESCRIPTION: For each "Field Unit" name in the argument list that is - * part of the field declaration, enter the name into the - * namespace. - * - ******************************************************************************/ - -acpi_status -acpi_ds_init_field_objects(union acpi_parse_object *op, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_parse_object *arg = NULL; - struct acpi_namespace_node *node; - u8 type = 0; - u32 flags; - - ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); - - /* Execute flag should always be set when this function is entered */ - - if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { - if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { - - /* bank_field Op is deferred, just return OK */ - - return_ACPI_STATUS(AE_OK); - } - - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - /* - * Get the field_list argument for this opcode. This is the start of the - * list of field elements. - */ - switch (walk_state->opcode) { - case AML_FIELD_OP: - arg = acpi_ps_get_arg(op, 2); - type = ACPI_TYPE_LOCAL_REGION_FIELD; - break; - - case AML_BANK_FIELD_OP: - arg = acpi_ps_get_arg(op, 4); - type = ACPI_TYPE_LOCAL_BANK_FIELD; - break; - - case AML_INDEX_FIELD_OP: - arg = acpi_ps_get_arg(op, 3); - type = ACPI_TYPE_LOCAL_INDEX_FIELD; - break; - - default: - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Creating new namespace node(s), should not already exist */ - - flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | - ACPI_NS_ERROR_IF_FOUND; - - /* Mark node(s) temporary if we are executing a method */ - - if (walk_state->method_node) { - flags |= ACPI_NS_TEMPORARY; - } - - /* - * Walk the list of entries in the field_list - * Note: field_list can be of zero length. In this case, Arg will be NULL. - */ - while (arg) { - /* - * Ignore OFFSET and ACCESSAS terms here; we are only interested in the - * field names in order to enter them into the namespace. - */ - if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { - status = acpi_ns_lookup(walk_state->scope_info, - (char *)&arg->named.name, type, - ACPI_IMODE_LOAD_PASS1, flags, - walk_state, &node); - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE((char *)&arg->named.name, - status); - if (status != AE_ALREADY_EXISTS) { - return_ACPI_STATUS(status); - } - - /* Name already exists, just ignore this error */ - - status = AE_OK; - } - - arg->common.node = node; - } - - /* Get the next field element in the list */ - - arg = arg->common.next; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_create_bank_field - * - * PARAMETERS: Op - Op containing the Field definition and args - * region_node - Object for the containing Operation Region - * walk_state - Current method state - * - * RETURN: Status - * - * DESCRIPTION: Create a new bank field in the specified operation region - * - ******************************************************************************/ - -acpi_status -acpi_ds_create_bank_field(union acpi_parse_object *op, - struct acpi_namespace_node *region_node, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_parse_object *arg; - struct acpi_create_field_info info; - - ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op); - - /* First arg is the name of the parent op_region (must already exist) */ - - arg = op->common.value.arg; - if (!region_node) { - status = - acpi_ns_lookup(walk_state->scope_info, - arg->common.value.name, ACPI_TYPE_REGION, - ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, - walk_state, ®ion_node); - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.name, status); - return_ACPI_STATUS(status); - } - } - - /* Second arg is the Bank Register (Field) (must already exist) */ - - arg = arg->common.next; - status = - acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, - ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT, walk_state, - &info.register_node); - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.string, status); - return_ACPI_STATUS(status); - } - - /* - * Third arg is the bank_value - * This arg is a term_arg, not a constant - * It will be evaluated later, by acpi_ds_eval_bank_field_operands - */ - arg = arg->common.next; - - /* Fourth arg is the field flags */ - - arg = arg->common.next; - info.field_flags = (u8) arg->common.value.integer; - - /* Each remaining arg is a Named Field */ - - info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; - info.region_node = region_node; - - /* - * Use Info.data_register_node to store bank_field Op - * It's safe because data_register_node will never be used when create bank field - * We store aml_start and aml_length in the bank_field Op for late evaluation - * Used in acpi_ex_prep_field_value(Info) - * - * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"? - */ - info.data_register_node = (struct acpi_namespace_node *)op; - - status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_create_index_field - * - * PARAMETERS: Op - Op containing the Field definition and args - * region_node - Object for the containing Operation Region - * ` walk_state - Current method state - * - * RETURN: Status - * - * DESCRIPTION: Create a new index field in the specified operation region - * - ******************************************************************************/ - -acpi_status -acpi_ds_create_index_field(union acpi_parse_object *op, - struct acpi_namespace_node *region_node, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_parse_object *arg; - struct acpi_create_field_info info; - - ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op); - - /* First arg is the name of the Index register (must already exist) */ - - arg = op->common.value.arg; - status = - acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, - ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT, walk_state, - &info.register_node); - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.string, status); - return_ACPI_STATUS(status); - } - - /* Second arg is the data register (must already exist) */ - - arg = arg->common.next; - status = - acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, - ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT, walk_state, - &info.data_register_node); - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.string, status); - return_ACPI_STATUS(status); - } - - /* Next arg is the field flags */ - - arg = arg->common.next; - info.field_flags = (u8) arg->common.value.integer; - - /* Each remaining arg is a Named Field */ - - info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD; - info.region_node = region_node; - - status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c deleted file mode 100644 index 4f1cdd823fcc..000000000000 --- a/drivers/acpi/dispatcher/dsinit.c +++ /dev/null @@ -1,205 +0,0 @@ -/****************************************************************************** - * - * Module Name: dsinit - Object initialization namespace walk - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_DISPATCHER -ACPI_MODULE_NAME("dsinit") - -/* Local prototypes */ -static acpi_status -acpi_ds_init_one_object(acpi_handle obj_handle, - u32 level, void *context, void **return_value); - -/******************************************************************************* - * - * FUNCTION: acpi_ds_init_one_object - * - * PARAMETERS: obj_handle - Node for the object - * Level - Current nesting level - * Context - Points to a init info struct - * return_value - Not used - * - * RETURN: Status - * - * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object - * within the namespace. - * - * Currently, the only objects that require initialization are: - * 1) Methods - * 2) Operation Regions - * - ******************************************************************************/ - -static acpi_status -acpi_ds_init_one_object(acpi_handle obj_handle, - u32 level, void *context, void **return_value) -{ - struct acpi_init_walk_info *info = - (struct acpi_init_walk_info *)context; - struct acpi_namespace_node *node = - (struct acpi_namespace_node *)obj_handle; - acpi_object_type type; - acpi_status status; - - ACPI_FUNCTION_ENTRY(); - - /* - * We are only interested in NS nodes owned by the table that - * was just loaded - */ - if (node->owner_id != info->owner_id) { - return (AE_OK); - } - - info->object_count++; - - /* And even then, we are only interested in a few object types */ - - type = acpi_ns_get_type(obj_handle); - - switch (type) { - case ACPI_TYPE_REGION: - - status = acpi_ds_initialize_region(obj_handle); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "During Region initialization %p [%4.4s]", - obj_handle, - acpi_ut_get_node_name(obj_handle))); - } - - info->op_region_count++; - break; - - case ACPI_TYPE_METHOD: - - info->method_count++; - break; - - case ACPI_TYPE_DEVICE: - - info->device_count++; - break; - - default: - break; - } - - /* - * We ignore errors from above, and always return OK, since - * we don't want to abort the walk on a single error. - */ - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_initialize_objects - * - * PARAMETERS: table_desc - Descriptor for parent ACPI table - * start_node - Root of subtree to be initialized. - * - * RETURN: Status - * - * DESCRIPTION: Walk the namespace starting at "StartNode" and perform any - * necessary initialization on the objects found therein - * - ******************************************************************************/ - -acpi_status -acpi_ds_initialize_objects(u32 table_index, - struct acpi_namespace_node * start_node) -{ - acpi_status status; - struct acpi_init_walk_info info; - struct acpi_table_header *table; - acpi_owner_id owner_id; - - ACPI_FUNCTION_TRACE(ds_initialize_objects); - - status = acpi_tb_get_owner_id(table_index, &owner_id); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "**** Starting initialization of namespace objects ****\n")); - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Parsing all Control Methods:")); - - info.method_count = 0; - info.op_region_count = 0; - info.object_count = 0; - info.device_count = 0; - info.table_index = table_index; - info.owner_id = owner_id; - - /* Walk entire namespace from the supplied root */ - - status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, - acpi_ds_init_one_object, &info, NULL); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); - } - - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n", - table->signature, owner_id, info.object_count, - info.device_count, info.method_count, - info.op_region_count)); - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "%hd Methods, %hd Regions\n", info.method_count, - info.op_region_count)); - - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c deleted file mode 100644 index 333c8560d9f8..000000000000 --- a/drivers/acpi/dispatcher/dsmethod.c +++ /dev/null @@ -1,629 +0,0 @@ -/****************************************************************************** - * - * Module Name: dsmethod - Parser/Interpreter interface - control method parsing - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include -#ifdef ACPI_DISASSEMBLER -#include -#endif - -#define _COMPONENT ACPI_DISPATCHER -ACPI_MODULE_NAME("dsmethod") - -/* Local prototypes */ -static acpi_status -acpi_ds_create_method_mutex(union acpi_operand_object *method_desc); - -/******************************************************************************* - * - * FUNCTION: acpi_ds_method_error - * - * PARAMETERS: Status - Execution status - * walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Called on method error. Invoke the global exception handler if - * present, dump the method data if the disassembler is configured - * - * Note: Allows the exception handler to change the status code - * - ******************************************************************************/ - -acpi_status -acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) -{ - ACPI_FUNCTION_ENTRY(); - - /* Ignore AE_OK and control exception codes */ - - if (ACPI_SUCCESS(status) || (status & AE_CODE_CONTROL)) { - return (status); - } - - /* Invoke the global exception handler */ - - if (acpi_gbl_exception_handler) { - - /* Exit the interpreter, allow handler to execute methods */ - - acpi_ex_exit_interpreter(); - - /* - * Handler can map the exception code to anything it wants, including - * AE_OK, in which case the executing method will not be aborted. - */ - status = acpi_gbl_exception_handler(status, - walk_state->method_node ? - walk_state->method_node-> - name.integer : 0, - walk_state->opcode, - walk_state->aml_offset, - NULL); - acpi_ex_enter_interpreter(); - } - - acpi_ds_clear_implicit_return(walk_state); - -#ifdef ACPI_DISASSEMBLER - if (ACPI_FAILURE(status)) { - - /* Display method locals/args if disassembler is present */ - - acpi_dm_dump_method_info(status, walk_state, walk_state->op); - } -#endif - - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_create_method_mutex - * - * PARAMETERS: obj_desc - The method object - * - * RETURN: Status - * - * DESCRIPTION: Create a mutex object for a serialized control method - * - ******************************************************************************/ - -static acpi_status -acpi_ds_create_method_mutex(union acpi_operand_object *method_desc) -{ - union acpi_operand_object *mutex_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE(ds_create_method_mutex); - - /* Create the new mutex object */ - - mutex_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX); - if (!mutex_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Create the actual OS Mutex */ - - status = acpi_os_create_mutex(&mutex_desc->mutex.os_mutex); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - mutex_desc->mutex.sync_level = method_desc->method.sync_level; - method_desc->method.mutex = mutex_desc; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_begin_method_execution - * - * PARAMETERS: method_node - Node of the method - * obj_desc - The method object - * walk_state - current state, NULL if not yet executing - * a method. - * - * RETURN: Status - * - * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, - * increments the thread count, and waits at the method semaphore - * for clearance to execute. - * - ******************************************************************************/ - -acpi_status -acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, - union acpi_operand_object *obj_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_PTR(ds_begin_method_execution, method_node); - - if (!method_node) { - return_ACPI_STATUS(AE_NULL_ENTRY); - } - - /* Prevent wraparound of thread count */ - - if (obj_desc->method.thread_count == ACPI_UINT8_MAX) { - ACPI_ERROR((AE_INFO, - "Method reached maximum reentrancy limit (255)")); - return_ACPI_STATUS(AE_AML_METHOD_LIMIT); - } - - /* - * If this method is serialized, we need to acquire the method mutex. - */ - if (obj_desc->method.method_flags & AML_METHOD_SERIALIZED) { - /* - * Create a mutex for the method if it is defined to be Serialized - * and a mutex has not already been created. We defer the mutex creation - * until a method is actually executed, to minimize the object count - */ - if (!obj_desc->method.mutex) { - status = acpi_ds_create_method_mutex(obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * The current_sync_level (per-thread) must be less than or equal to - * the sync level of the method. This mechanism provides some - * deadlock prevention - * - * Top-level method invocation has no walk state at this point - */ - if (walk_state && - (walk_state->thread->current_sync_level > - obj_desc->method.mutex->mutex.sync_level)) { - ACPI_ERROR((AE_INFO, - "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%d)", - acpi_ut_get_node_name(method_node), - walk_state->thread->current_sync_level)); - - return_ACPI_STATUS(AE_AML_MUTEX_ORDER); - } - - /* - * Obtain the method mutex if necessary. Do not acquire mutex for a - * recursive call. - */ - if (!walk_state || - !obj_desc->method.mutex->mutex.thread_id || - (walk_state->thread->thread_id != - obj_desc->method.mutex->mutex.thread_id)) { - /* - * Acquire the method mutex. This releases the interpreter if we - * block (and reacquires it before it returns) - */ - status = - acpi_ex_system_wait_mutex(obj_desc->method.mutex-> - mutex.os_mutex, - ACPI_WAIT_FOREVER); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Update the mutex and walk info and save the original sync_level */ - - if (walk_state) { - obj_desc->method.mutex->mutex. - original_sync_level = - walk_state->thread->current_sync_level; - - obj_desc->method.mutex->mutex.thread_id = - walk_state->thread->thread_id; - walk_state->thread->current_sync_level = - obj_desc->method.sync_level; - } else { - obj_desc->method.mutex->mutex. - original_sync_level = - obj_desc->method.mutex->mutex.sync_level; - } - } - - /* Always increase acquisition depth */ - - obj_desc->method.mutex->mutex.acquisition_depth++; - } - - /* - * Allocate an Owner ID for this method, only if this is the first thread - * to begin concurrent execution. We only need one owner_id, even if the - * method is invoked recursively. - */ - if (!obj_desc->method.owner_id) { - status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - } - - /* - * Increment the method parse tree thread count since it has been - * reentered one more time (even if it is the same thread) - */ - obj_desc->method.thread_count++; - return_ACPI_STATUS(status); - - cleanup: - /* On error, must release the method mutex (if present) */ - - if (obj_desc->method.mutex) { - acpi_os_release_mutex(obj_desc->method.mutex->mutex.os_mutex); - } - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_call_control_method - * - * PARAMETERS: Thread - Info for this thread - * this_walk_state - Current walk state - * Op - Current Op to be walked - * - * RETURN: Status - * - * DESCRIPTION: Transfer execution to a called control method - * - ******************************************************************************/ - -acpi_status -acpi_ds_call_control_method(struct acpi_thread_state *thread, - struct acpi_walk_state *this_walk_state, - union acpi_parse_object *op) -{ - acpi_status status; - struct acpi_namespace_node *method_node; - struct acpi_walk_state *next_walk_state = NULL; - union acpi_operand_object *obj_desc; - struct acpi_evaluate_info *info; - u32 i; - - ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state); - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Calling method %p, currentstate=%p\n", - this_walk_state->prev_op, this_walk_state)); - - /* - * Get the namespace entry for the control method we are about to call - */ - method_node = this_walk_state->method_call_node; - if (!method_node) { - return_ACPI_STATUS(AE_NULL_ENTRY); - } - - obj_desc = acpi_ns_get_attached_object(method_node); - if (!obj_desc) { - return_ACPI_STATUS(AE_NULL_OBJECT); - } - - /* Init for new method, possibly wait on method mutex */ - - status = acpi_ds_begin_method_execution(method_node, obj_desc, - this_walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Begin method parse/execution. Create a new walk state */ - - next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, - NULL, obj_desc, thread); - if (!next_walk_state) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * The resolved arguments were put on the previous walk state's operand - * stack. Operands on the previous walk state stack always - * start at index 0. Also, null terminate the list of arguments - */ - this_walk_state->operands[this_walk_state->num_operands] = NULL; - - /* - * Allocate and initialize the evaluation information block - * TBD: this is somewhat inefficient, should change interface to - * ds_init_aml_walk. For now, keeps this struct off the CPU stack - */ - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); - if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - info->parameters = &this_walk_state->operands[0]; - - status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node, - obj_desc->method.aml_start, - obj_desc->method.aml_length, info, - ACPI_IMODE_EXECUTE); - - ACPI_FREE(info); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* - * Delete the operands on the previous walkstate operand stack - * (they were copied to new objects) - */ - for (i = 0; i < obj_desc->method.param_count; i++) { - acpi_ut_remove_reference(this_walk_state->operands[i]); - this_walk_state->operands[i] = NULL; - } - - /* Clear the operand stack */ - - this_walk_state->num_operands = 0; - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", - method_node->name.ascii, next_walk_state)); - - /* Invoke an internal method if necessary */ - - if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { - status = obj_desc->method.implementation(next_walk_state); - if (status == AE_OK) { - status = AE_CTRL_TERMINATE; - } - } - - return_ACPI_STATUS(status); - - cleanup: - - /* On error, we must terminate the method properly */ - - acpi_ds_terminate_control_method(obj_desc, next_walk_state); - if (next_walk_state) { - acpi_ds_delete_walk_state(next_walk_state); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_restart_control_method - * - * PARAMETERS: walk_state - State for preempted method (caller) - * return_desc - Return value from the called method - * - * RETURN: Status - * - * DESCRIPTION: Restart a method that was preempted by another (nested) method - * invocation. Handle the return value (if any) from the callee. - * - ******************************************************************************/ - -acpi_status -acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, - union acpi_operand_object *return_desc) -{ - acpi_status status; - int same_as_implicit_return; - - ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state); - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n", - acpi_ut_get_node_name(walk_state->method_node), - walk_state->method_call_op, return_desc)); - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n", - walk_state->return_used, - walk_state->results, walk_state)); - - /* Did the called method return a value? */ - - if (return_desc) { - - /* Is the implicit return object the same as the return desc? */ - - same_as_implicit_return = - (walk_state->implicit_return_obj == return_desc); - - /* Are we actually going to use the return value? */ - - if (walk_state->return_used) { - - /* Save the return value from the previous method */ - - status = acpi_ds_result_push(return_desc, walk_state); - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(return_desc); - return_ACPI_STATUS(status); - } - - /* - * Save as THIS method's return value in case it is returned - * immediately to yet another method - */ - walk_state->return_desc = return_desc; - } - - /* - * The following code is the optional support for the so-called - * "implicit return". Some AML code assumes that the last value of the - * method is "implicitly" returned to the caller, in the absence of an - * explicit return value. - * - * Just save the last result of the method as the return value. - * - * NOTE: this is optional because the ASL language does not actually - * support this behavior. - */ - else if (!acpi_ds_do_implicit_return - (return_desc, walk_state, FALSE) - || same_as_implicit_return) { - /* - * Delete the return value if it will not be used by the - * calling method or remove one reference if the explicit return - * is the same as the implicit return value. - */ - acpi_ut_remove_reference(return_desc); - } - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_terminate_control_method - * - * PARAMETERS: method_desc - Method object - * walk_state - State associated with the method - * - * RETURN: None - * - * DESCRIPTION: Terminate a control method. Delete everything that the method - * created, delete all locals and arguments, and delete the parse - * tree if requested. - * - * MUTEX: Interpreter is locked - * - ******************************************************************************/ - -void -acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, - struct acpi_walk_state *walk_state) -{ - - ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state); - - /* method_desc is required, walk_state is optional */ - - if (!method_desc) { - return_VOID; - } - - if (walk_state) { - - /* Delete all arguments and locals */ - - acpi_ds_method_data_delete_all(walk_state); - - /* - * If method is serialized, release the mutex and restore the - * current sync level for this thread - */ - if (method_desc->method.mutex) { - - /* Acquisition Depth handles recursive calls */ - - method_desc->method.mutex->mutex.acquisition_depth--; - if (!method_desc->method.mutex->mutex.acquisition_depth) { - walk_state->thread->current_sync_level = - method_desc->method.mutex->mutex. - original_sync_level; - - acpi_os_release_mutex(method_desc->method. - mutex->mutex.os_mutex); - method_desc->method.mutex->mutex.thread_id = NULL; - } - } - - /* - * Delete any namespace objects created anywhere within - * the namespace by the execution of this method - */ - acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id); - } - - /* Decrement the thread count on the method */ - - if (method_desc->method.thread_count) { - method_desc->method.thread_count--; - } else { - ACPI_ERROR((AE_INFO, "Invalid zero thread count in method")); - } - - /* Are there any other threads currently executing this method? */ - - if (method_desc->method.thread_count) { - /* - * Additional threads. Do not release the owner_id in this case, - * we immediately reuse it for the next thread executing this method - */ - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "*** Completed execution of one thread, %d threads remaining\n", - method_desc->method.thread_count)); - } else { - /* This is the only executing thread for this method */ - - /* - * Support to dynamically change a method from not_serialized to - * Serialized if it appears that the method is incorrectly written and - * does not support multiple thread execution. The best example of this - * is if such a method creates namespace objects and blocks. A second - * thread will fail with an AE_ALREADY_EXISTS exception - * - * This code is here because we must wait until the last thread exits - * before creating the synchronization semaphore. - */ - if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED) - && (!method_desc->method.mutex)) { - (void)acpi_ds_create_method_mutex(method_desc); - } - - /* No more threads, we can free the owner_id */ - - acpi_ut_release_owner_id(&method_desc->method.owner_id); - } - - return_VOID; -} diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c deleted file mode 100644 index a1a11996a651..000000000000 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ /dev/null @@ -1,718 +0,0 @@ -/******************************************************************************* - * - * Module Name: dsmthdat - control method arguments and local variables - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_DISPATCHER -ACPI_MODULE_NAME("dsmthdat") - -/* Local prototypes */ -static void -acpi_ds_method_data_delete_value(u8 type, - u32 index, struct acpi_walk_state *walk_state); - -static acpi_status -acpi_ds_method_data_set_value(u8 type, - u32 index, - union acpi_operand_object *object, - struct acpi_walk_state *walk_state); - -#ifdef ACPI_OBSOLETE_FUNCTIONS -acpi_object_type -acpi_ds_method_data_get_type(u16 opcode, - u32 index, struct acpi_walk_state *walk_state); -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ds_method_data_init - * - * PARAMETERS: walk_state - Current walk state object - * - * RETURN: Status - * - * DESCRIPTION: Initialize the data structures that hold the method's arguments - * and locals. The data struct is an array of namespace nodes for - * each - this allows ref_of and de_ref_of to work properly for these - * special data types. - * - * NOTES: walk_state fields are initialized to zero by the - * ACPI_ALLOCATE_ZEROED(). - * - * A pseudo-Namespace Node is assigned to each argument and local - * so that ref_of() can return a pointer to the Node. - * - ******************************************************************************/ - -void acpi_ds_method_data_init(struct acpi_walk_state *walk_state) -{ - u32 i; - - ACPI_FUNCTION_TRACE(ds_method_data_init); - - /* Init the method arguments */ - - for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) { - ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name, - NAMEOF_ARG_NTE); - walk_state->arguments[i].name.integer |= (i << 24); - walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED; - walk_state->arguments[i].type = ACPI_TYPE_ANY; - walk_state->arguments[i].flags = - ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG; - } - - /* Init the method locals */ - - for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) { - ACPI_MOVE_32_TO_32(&walk_state->local_variables[i].name, - NAMEOF_LOCAL_NTE); - - walk_state->local_variables[i].name.integer |= (i << 24); - walk_state->local_variables[i].descriptor_type = - ACPI_DESC_TYPE_NAMED; - walk_state->local_variables[i].type = ACPI_TYPE_ANY; - walk_state->local_variables[i].flags = - ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL; - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_method_data_delete_all - * - * PARAMETERS: walk_state - Current walk state object - * - * RETURN: None - * - * DESCRIPTION: Delete method locals and arguments. Arguments are only - * deleted if this method was called from another method. - * - ******************************************************************************/ - -void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state) -{ - u32 index; - - ACPI_FUNCTION_TRACE(ds_method_data_delete_all); - - /* Detach the locals */ - - for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) { - if (walk_state->local_variables[index].object) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Local%d=%p\n", - index, - walk_state->local_variables[index]. - object)); - - /* Detach object (if present) and remove a reference */ - - acpi_ns_detach_object(&walk_state-> - local_variables[index]); - } - } - - /* Detach the arguments */ - - for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) { - if (walk_state->arguments[index].object) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Arg%d=%p\n", - index, - walk_state->arguments[index].object)); - - /* Detach object (if present) and remove a reference */ - - acpi_ns_detach_object(&walk_state->arguments[index]); - } - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_method_data_init_args - * - * PARAMETERS: *Params - Pointer to a parameter list for the method - * max_param_count - The arg count for this method - * walk_state - Current walk state object - * - * RETURN: Status - * - * DESCRIPTION: Initialize arguments for a method. The parameter list is a list - * of ACPI operand objects, either null terminated or whose length - * is defined by max_param_count. - * - ******************************************************************************/ - -acpi_status -acpi_ds_method_data_init_args(union acpi_operand_object **params, - u32 max_param_count, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - u32 index = 0; - - ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params); - - if (!params) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "No param list passed to method\n")); - return_ACPI_STATUS(AE_OK); - } - - /* Copy passed parameters into the new method stack frame */ - - while ((index < ACPI_METHOD_NUM_ARGS) && - (index < max_param_count) && params[index]) { - /* - * A valid parameter. - * Store the argument in the method/walk descriptor. - * Do not copy the arg in order to implement call by reference - */ - status = acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index, - params[index], - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - index++; - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%d args passed to method\n", index)); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_method_data_get_node - * - * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or - * ACPI_REFCLASS_ARG - * Index - Which Local or Arg whose type to get - * walk_state - Current walk state object - * Node - Where the node is returned. - * - * RETURN: Status and node - * - * DESCRIPTION: Get the Node associated with a local or arg. - * - ******************************************************************************/ - -acpi_status -acpi_ds_method_data_get_node(u8 type, - u32 index, - struct acpi_walk_state *walk_state, - struct acpi_namespace_node **node) -{ - ACPI_FUNCTION_TRACE(ds_method_data_get_node); - - /* - * Method Locals and Arguments are supported - */ - switch (type) { - case ACPI_REFCLASS_LOCAL: - - if (index > ACPI_METHOD_MAX_LOCAL) { - ACPI_ERROR((AE_INFO, - "Local index %d is invalid (max %d)", - index, ACPI_METHOD_MAX_LOCAL)); - return_ACPI_STATUS(AE_AML_INVALID_INDEX); - } - - /* Return a pointer to the pseudo-node */ - - *node = &walk_state->local_variables[index]; - break; - - case ACPI_REFCLASS_ARG: - - if (index > ACPI_METHOD_MAX_ARG) { - ACPI_ERROR((AE_INFO, - "Arg index %d is invalid (max %d)", - index, ACPI_METHOD_MAX_ARG)); - return_ACPI_STATUS(AE_AML_INVALID_INDEX); - } - - /* Return a pointer to the pseudo-node */ - - *node = &walk_state->arguments[index]; - break; - - default: - ACPI_ERROR((AE_INFO, "Type %d is invalid", type)); - return_ACPI_STATUS(AE_TYPE); - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_method_data_set_value - * - * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or - * ACPI_REFCLASS_ARG - * Index - Which Local or Arg to get - * Object - Object to be inserted into the stack entry - * walk_state - Current walk state object - * - * RETURN: Status - * - * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index. - * Note: There is no "implicit conversion" for locals. - * - ******************************************************************************/ - -static acpi_status -acpi_ds_method_data_set_value(u8 type, - u32 index, - union acpi_operand_object *object, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - struct acpi_namespace_node *node; - - ACPI_FUNCTION_TRACE(ds_method_data_set_value); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "NewObj %p Type %2.2X, Refs=%d [%s]\n", object, - type, object->common.reference_count, - acpi_ut_get_type_name(object->common.type))); - - /* Get the namespace node for the arg/local */ - - status = acpi_ds_method_data_get_node(type, index, walk_state, &node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Increment ref count so object can't be deleted while installed. - * NOTE: We do not copy the object in order to preserve the call by - * reference semantics of ACPI Control Method invocation. - * (See ACPI Specification 2.0_c) - */ - acpi_ut_add_reference(object); - - /* Install the object */ - - node->object = object; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_method_data_get_value - * - * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or - * ACPI_REFCLASS_ARG - * Index - Which local_var or argument to get - * walk_state - Current walk state object - * dest_desc - Where Arg or Local value is returned - * - * RETURN: Status - * - * DESCRIPTION: Retrieve value of selected Arg or Local for this method - * Used only in acpi_ex_resolve_to_value(). - * - ******************************************************************************/ - -acpi_status -acpi_ds_method_data_get_value(u8 type, - u32 index, - struct acpi_walk_state *walk_state, - union acpi_operand_object **dest_desc) -{ - acpi_status status; - struct acpi_namespace_node *node; - union acpi_operand_object *object; - - ACPI_FUNCTION_TRACE(ds_method_data_get_value); - - /* Validate the object descriptor */ - - if (!dest_desc) { - ACPI_ERROR((AE_INFO, "Null object descriptor pointer")); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Get the namespace node for the arg/local */ - - status = acpi_ds_method_data_get_node(type, index, walk_state, &node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get the object from the node */ - - object = node->object; - - /* Examine the returned object, it must be valid. */ - - if (!object) { - /* - * Index points to uninitialized object. - * This means that either 1) The expected argument was - * not passed to the method, or 2) A local variable - * was referenced by the method (via the ASL) - * before it was initialized. Either case is an error. - */ - - /* If slack enabled, init the local_x/arg_x to an Integer of value zero */ - - if (acpi_gbl_enable_interpreter_slack) { - object = - acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!object) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - object->integer.value = 0; - node->object = object; - } - - /* Otherwise, return the error */ - - else - switch (type) { - case ACPI_REFCLASS_ARG: - - ACPI_ERROR((AE_INFO, - "Uninitialized Arg[%d] at node %p", - index, node)); - - return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); - - case ACPI_REFCLASS_LOCAL: - - ACPI_ERROR((AE_INFO, - "Uninitialized Local[%d] at node %p", - index, node)); - - return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL); - - default: - - ACPI_ERROR((AE_INFO, - "Not a Arg/Local opcode: %X", - type)); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - } - - /* - * The Index points to an initialized and valid object. - * Return an additional reference to the object - */ - *dest_desc = object; - acpi_ut_add_reference(object); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_method_data_delete_value - * - * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or - * ACPI_REFCLASS_ARG - * Index - Which local_var or argument to delete - * walk_state - Current walk state object - * - * RETURN: None - * - * DESCRIPTION: Delete the entry at Opcode:Index. Inserts - * a null into the stack slot after the object is deleted. - * - ******************************************************************************/ - -static void -acpi_ds_method_data_delete_value(u8 type, - u32 index, struct acpi_walk_state *walk_state) -{ - acpi_status status; - struct acpi_namespace_node *node; - union acpi_operand_object *object; - - ACPI_FUNCTION_TRACE(ds_method_data_delete_value); - - /* Get the namespace node for the arg/local */ - - status = acpi_ds_method_data_get_node(type, index, walk_state, &node); - if (ACPI_FAILURE(status)) { - return_VOID; - } - - /* Get the associated object */ - - object = acpi_ns_get_attached_object(node); - - /* - * Undefine the Arg or Local by setting its descriptor - * pointer to NULL. Locals/Args can contain both - * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs - */ - node->object = NULL; - - if ((object) && - (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_OPERAND)) { - /* - * There is a valid object. - * Decrement the reference count by one to balance the - * increment when the object was stored. - */ - acpi_ut_remove_reference(object); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_store_object_to_local - * - * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or - * ACPI_REFCLASS_ARG - * Index - Which Local or Arg to set - * obj_desc - Value to be stored - * walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed - * as the new value for the Arg or Local and the reference count - * for obj_desc is incremented. - * - ******************************************************************************/ - -acpi_status -acpi_ds_store_object_to_local(u8 type, - u32 index, - union acpi_operand_object *obj_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - struct acpi_namespace_node *node; - union acpi_operand_object *current_obj_desc; - union acpi_operand_object *new_obj_desc; - - ACPI_FUNCTION_TRACE(ds_store_object_to_local); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%d Obj=%p\n", - type, index, obj_desc)); - - /* Parameter validation */ - - if (!obj_desc) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Get the namespace node for the arg/local */ - - status = acpi_ds_method_data_get_node(type, index, walk_state, &node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - current_obj_desc = acpi_ns_get_attached_object(node); - if (current_obj_desc == obj_desc) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n", - obj_desc)); - return_ACPI_STATUS(status); - } - - /* - * If the reference count on the object is more than one, we must - * take a copy of the object before we store. A reference count - * of exactly 1 means that the object was just created during the - * evaluation of an expression, and we can safely use it since it - * is not used anywhere else. - */ - new_obj_desc = obj_desc; - if (obj_desc->common.reference_count > 1) { - status = - acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * If there is an object already in this slot, we either - * have to delete it, or if this is an argument and there - * is an object reference stored there, we have to do - * an indirect store! - */ - if (current_obj_desc) { - /* - * Check for an indirect store if an argument - * contains an object reference (stored as an Node). - * We don't allow this automatic dereferencing for - * locals, since a store to a local should overwrite - * anything there, including an object reference. - * - * If both Arg0 and Local0 contain ref_of (Local4): - * - * Store (1, Arg0) - Causes indirect store to local4 - * Store (1, Local0) - Stores 1 in local0, overwriting - * the reference to local4 - * Store (1, de_refof (Local0)) - Causes indirect store to local4 - * - * Weird, but true. - */ - if (type == ACPI_REFCLASS_ARG) { - /* - * If we have a valid reference object that came from ref_of(), - * do the indirect store - */ - if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) == - ACPI_DESC_TYPE_OPERAND) - && (current_obj_desc->common.type == - ACPI_TYPE_LOCAL_REFERENCE) - && (current_obj_desc->reference.class == - ACPI_REFCLASS_REFOF)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Arg (%p) is an ObjRef(Node), storing in node %p\n", - new_obj_desc, - current_obj_desc)); - - /* - * Store this object to the Node (perform the indirect store) - * NOTE: No implicit conversion is performed, as per the ACPI - * specification rules on storing to Locals/Args. - */ - status = - acpi_ex_store_object_to_node(new_obj_desc, - current_obj_desc-> - reference. - object, - walk_state, - ACPI_NO_IMPLICIT_CONVERSION); - - /* Remove local reference if we copied the object above */ - - if (new_obj_desc != obj_desc) { - acpi_ut_remove_reference(new_obj_desc); - } - return_ACPI_STATUS(status); - } - } - - /* Delete the existing object before storing the new one */ - - acpi_ds_method_data_delete_value(type, index, walk_state); - } - - /* - * Install the Obj descriptor (*new_obj_desc) into - * the descriptor for the Arg or Local. - * (increments the object reference count by one) - */ - status = - acpi_ds_method_data_set_value(type, index, new_obj_desc, - walk_state); - - /* Remove local reference if we copied the object above */ - - if (new_obj_desc != obj_desc) { - acpi_ut_remove_reference(new_obj_desc); - } - - return_ACPI_STATUS(status); -} - -#ifdef ACPI_OBSOLETE_FUNCTIONS -/******************************************************************************* - * - * FUNCTION: acpi_ds_method_data_get_type - * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP - * Index - Which Local or Arg whose type to get - * walk_state - Current walk state object - * - * RETURN: Data type of current value of the selected Arg or Local - * - * DESCRIPTION: Get the type of the object stored in the Local or Arg - * - ******************************************************************************/ - -acpi_object_type -acpi_ds_method_data_get_type(u16 opcode, - u32 index, struct acpi_walk_state *walk_state) -{ - acpi_status status; - struct acpi_namespace_node *node; - union acpi_operand_object *object; - - ACPI_FUNCTION_TRACE(ds_method_data_get_type); - - /* Get the namespace node for the arg/local */ - - status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); - if (ACPI_FAILURE(status)) { - return_VALUE((ACPI_TYPE_NOT_FOUND)); - } - - /* Get the object */ - - object = acpi_ns_get_attached_object(node); - if (!object) { - - /* Uninitialized local/arg, return TYPE_ANY */ - - return_VALUE(ACPI_TYPE_ANY); - } - - /* Get the object type */ - - return_VALUE(ACPI_GET_OBJECT_TYPE(object)); -} -#endif diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c deleted file mode 100644 index 6e6c73cc39ff..000000000000 --- a/drivers/acpi/dispatcher/dsobject.c +++ /dev/null @@ -1,813 +0,0 @@ -/****************************************************************************** - * - * Module Name: dsobject - Dispatcher object management routines - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_DISPATCHER -ACPI_MODULE_NAME("dsobject") - -/* Local prototypes */ -static acpi_status -acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, - union acpi_operand_object **obj_desc_ptr); - -#ifndef ACPI_NO_METHOD_EXECUTION -/******************************************************************************* - * - * FUNCTION: acpi_ds_build_internal_object - * - * PARAMETERS: walk_state - Current walk state - * Op - Parser object to be translated - * obj_desc_ptr - Where the ACPI internal object is returned - * - * RETURN: Status - * - * DESCRIPTION: Translate a parser Op object to the equivalent namespace object - * Simple objects are any objects other than a package object! - * - ******************************************************************************/ - -static acpi_status -acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, - union acpi_operand_object **obj_desc_ptr) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE(ds_build_internal_object); - - *obj_desc_ptr = NULL; - if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { - /* - * This is a named object reference. If this name was - * previously looked up in the namespace, it was stored in this op. - * Otherwise, go ahead and look it up now - */ - if (!op->common.node) { - status = acpi_ns_lookup(walk_state->scope_info, - op->common.value.string, - ACPI_TYPE_ANY, - ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT | - ACPI_NS_DONT_OPEN_SCOPE, NULL, - ACPI_CAST_INDIRECT_PTR(struct - acpi_namespace_node, - &(op-> - common. - node))); - if (ACPI_FAILURE(status)) { - - /* Check if we are resolving a named reference within a package */ - - if ((status == AE_NOT_FOUND) - && (acpi_gbl_enable_interpreter_slack) - && - ((op->common.parent->common.aml_opcode == - AML_PACKAGE_OP) - || (op->common.parent->common.aml_opcode == - AML_VAR_PACKAGE_OP))) { - /* - * We didn't find the target and we are populating elements - * of a package - ignore if slack enabled. Some ASL code - * contains dangling invalid references in packages and - * expects that no exception will be issued. Leave the - * element as a null element. It cannot be used, but it - * can be overwritten by subsequent ASL code - this is - * typically the case. - */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Ignoring unresolved reference in package [%4.4s]\n", - walk_state-> - scope_info->scope. - node->name.ascii)); - - return_ACPI_STATUS(AE_OK); - } else { - ACPI_ERROR_NAMESPACE(op->common.value. - string, status); - } - - return_ACPI_STATUS(status); - } - } - - /* Special object resolution for elements of a package */ - - if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || - (op->common.parent->common.aml_opcode == - AML_VAR_PACKAGE_OP)) { - /* - * Attempt to resolve the node to a value before we insert it into - * the package. If this is a reference to a common data type, - * resolve it immediately. According to the ACPI spec, package - * elements can only be "data objects" or method references. - * Attempt to resolve to an Integer, Buffer, String or Package. - * If cannot, return the named reference (for things like Devices, - * Methods, etc.) Buffer Fields and Fields will resolve to simple - * objects (int/buf/str/pkg). - * - * NOTE: References to things like Devices, Methods, Mutexes, etc. - * will remain as named references. This behavior is not described - * in the ACPI spec, but it appears to be an oversight. - */ - obj_desc = - ACPI_CAST_PTR(union acpi_operand_object, - op->common.node); - - status = - acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR - (struct - acpi_namespace_node, - &obj_desc), - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - switch (op->common.node->type) { - /* - * For these types, we need the actual node, not the subobject. - * However, the subobject did not get an extra reference count above. - * - * TBD: should ex_resolve_node_to_value be changed to fix this? - */ - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_THERMAL: - - acpi_ut_add_reference(op->common.node->object); - - /*lint -fallthrough */ - /* - * For these types, we need the actual node, not the subobject. - * The subobject got an extra reference count in ex_resolve_node_to_value. - */ - case ACPI_TYPE_MUTEX: - case ACPI_TYPE_METHOD: - case ACPI_TYPE_POWER: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_EVENT: - case ACPI_TYPE_REGION: - - /* We will create a reference object for these types below */ - break; - - default: - /* - * All other types - the node was resolved to an actual - * object, we are done. - */ - goto exit; - } - } - } - - /* Create and init a new internal ACPI object */ - - obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info - (op->common.aml_opcode))-> - object_type); - if (!obj_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - status = - acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode, - &obj_desc); - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); - } - - exit: - *obj_desc_ptr = obj_desc; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_build_internal_buffer_obj - * - * PARAMETERS: walk_state - Current walk state - * Op - Parser object to be translated - * buffer_length - Length of the buffer - * obj_desc_ptr - Where the ACPI internal object is returned - * - * RETURN: Status - * - * DESCRIPTION: Translate a parser Op package object to the equivalent - * namespace object - * - ******************************************************************************/ - -acpi_status -acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, - u32 buffer_length, - union acpi_operand_object **obj_desc_ptr) -{ - union acpi_parse_object *arg; - union acpi_operand_object *obj_desc; - union acpi_parse_object *byte_list; - u32 byte_list_length = 0; - - ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj); - - /* - * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". - * The buffer object already exists (from the NS node), otherwise it must - * be created. - */ - obj_desc = *obj_desc_ptr; - if (!obj_desc) { - - /* Create a new buffer object */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); - *obj_desc_ptr = obj_desc; - if (!obj_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - } - - /* - * Second arg is the buffer data (optional) byte_list can be either - * individual bytes or a string initializer. In either case, a - * byte_list appears in the AML. - */ - arg = op->common.value.arg; /* skip first arg */ - - byte_list = arg->named.next; - if (byte_list) { - if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) { - ACPI_ERROR((AE_INFO, - "Expecting bytelist, got AML opcode %X in op %p", - byte_list->common.aml_opcode, byte_list)); - - acpi_ut_remove_reference(obj_desc); - return (AE_TYPE); - } - - byte_list_length = (u32) byte_list->common.value.integer; - } - - /* - * The buffer length (number of bytes) will be the larger of: - * 1) The specified buffer length and - * 2) The length of the initializer byte list - */ - obj_desc->buffer.length = buffer_length; - if (byte_list_length > buffer_length) { - obj_desc->buffer.length = byte_list_length; - } - - /* Allocate the buffer */ - - if (obj_desc->buffer.length == 0) { - obj_desc->buffer.pointer = NULL; - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Buffer defined with zero length in AML, creating\n")); - } else { - obj_desc->buffer.pointer = - ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length); - if (!obj_desc->buffer.pointer) { - acpi_ut_delete_object_desc(obj_desc); - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Initialize buffer from the byte_list (if present) */ - - if (byte_list) { - ACPI_MEMCPY(obj_desc->buffer.pointer, - byte_list->named.data, byte_list_length); - } - } - - obj_desc->buffer.flags |= AOPOBJ_DATA_VALID; - op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_build_internal_package_obj - * - * PARAMETERS: walk_state - Current walk state - * Op - Parser object to be translated - * element_count - Number of elements in the package - this is - * the num_elements argument to Package() - * obj_desc_ptr - Where the ACPI internal object is returned - * - * RETURN: Status - * - * DESCRIPTION: Translate a parser Op package object to the equivalent - * namespace object - * - * NOTE: The number of elements in the package will be always be the num_elements - * count, regardless of the number of elements in the package list. If - * num_elements is smaller, only that many package list elements are used. - * if num_elements is larger, the Package object is padded out with - * objects of type Uninitialized (as per ACPI spec.) - * - * Even though the ASL compilers do not allow num_elements to be smaller - * than the Package list length (for the fixed length package opcode), some - * BIOS code modifies the AML on the fly to adjust the num_elements, and - * this code compensates for that. This also provides compatibility with - * other AML interpreters. - * - ******************************************************************************/ - -acpi_status -acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, - u32 element_count, - union acpi_operand_object **obj_desc_ptr) -{ - union acpi_parse_object *arg; - union acpi_parse_object *parent; - union acpi_operand_object *obj_desc = NULL; - acpi_status status = AE_OK; - unsigned i; - u16 index; - u16 reference_count; - - ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); - - /* Find the parent of a possibly nested package */ - - parent = op->common.parent; - while ((parent->common.aml_opcode == AML_PACKAGE_OP) || - (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { - parent = parent->common.parent; - } - - /* - * If we are evaluating a Named package object "Name (xxxx, Package)", - * the package object already exists, otherwise it must be created. - */ - obj_desc = *obj_desc_ptr; - if (!obj_desc) { - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE); - *obj_desc_ptr = obj_desc; - if (!obj_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - obj_desc->package.node = parent->common.node; - } - - /* - * Allocate the element array (array of pointers to the individual - * objects) based on the num_elements parameter. Add an extra pointer slot - * so that the list is always null terminated. - */ - obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) - element_count + - 1) * sizeof(void *)); - - if (!obj_desc->package.elements) { - acpi_ut_delete_object_desc(obj_desc); - return_ACPI_STATUS(AE_NO_MEMORY); - } - - obj_desc->package.count = element_count; - - /* - * Initialize the elements of the package, up to the num_elements count. - * Package is automatically padded with uninitialized (NULL) elements - * if num_elements is greater than the package list length. Likewise, - * Package is truncated if num_elements is less than the list length. - */ - arg = op->common.value.arg; - arg = arg->common.next; - for (i = 0; arg && (i < element_count); i++) { - if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { - if (arg->common.node->type == ACPI_TYPE_METHOD) { - /* - * A method reference "looks" to the parser to be a method - * invocation, so we special case it here - */ - arg->common.aml_opcode = AML_INT_NAMEPATH_OP; - status = - acpi_ds_build_internal_object(walk_state, - arg, - &obj_desc-> - package. - elements[i]); - } else { - /* This package element is already built, just get it */ - - obj_desc->package.elements[i] = - ACPI_CAST_PTR(union acpi_operand_object, - arg->common.node); - } - } else { - status = acpi_ds_build_internal_object(walk_state, arg, - &obj_desc-> - package. - elements[i]); - } - - if (*obj_desc_ptr) { - - /* Existing package, get existing reference count */ - - reference_count = - (*obj_desc_ptr)->common.reference_count; - if (reference_count > 1) { - - /* Make new element ref count match original ref count */ - - for (index = 0; index < (reference_count - 1); - index++) { - acpi_ut_add_reference((obj_desc-> - package. - elements[i])); - } - } - } - - arg = arg->common.next; - } - - /* Check for match between num_elements and actual length of package_list */ - - if (arg) { - /* - * num_elements was exhausted, but there are remaining elements in the - * package_list. - * - * Note: technically, this is an error, from ACPI spec: "It is an error - * for NumElements to be less than the number of elements in the - * PackageList". However, for now, we just print an error message and - * no exception is returned. - */ - while (arg) { - - /* Find out how many elements there really are */ - - i++; - arg = arg->common.next; - } - - ACPI_WARNING((AE_INFO, - "Package List length (%X) larger than NumElements count (%X), truncated\n", - i, element_count)); - } else if (i < element_count) { - /* - * Arg list (elements) was exhausted, but we did not reach num_elements count. - * Note: this is not an error, the package is padded out with NULLs. - */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Package List length (%X) smaller than NumElements count (%X), padded with null elements\n", - i, element_count)); - } - - obj_desc->package.flags |= AOPOBJ_DATA_VALID; - op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_create_node - * - * PARAMETERS: walk_state - Current walk state - * Node - NS Node to be initialized - * Op - Parser object to be translated - * - * RETURN: Status - * - * DESCRIPTION: Create the object to be associated with a namespace node - * - ******************************************************************************/ - -acpi_status -acpi_ds_create_node(struct acpi_walk_state *walk_state, - struct acpi_namespace_node *node, - union acpi_parse_object *op) -{ - acpi_status status; - union acpi_operand_object *obj_desc; - - ACPI_FUNCTION_TRACE_PTR(ds_create_node, op); - - /* - * Because of the execution pass through the non-control-method - * parts of the table, we can arrive here twice. Only init - * the named object node the first time through - */ - if (acpi_ns_get_attached_object(node)) { - return_ACPI_STATUS(AE_OK); - } - - if (!op->common.value.arg) { - - /* No arguments, there is nothing to do */ - - return_ACPI_STATUS(AE_OK); - } - - /* Build an internal object for the argument(s) */ - - status = acpi_ds_build_internal_object(walk_state, op->common.value.arg, - &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Re-type the object according to its argument */ - - node->type = ACPI_GET_OBJECT_TYPE(obj_desc); - - /* Attach obj to node */ - - status = acpi_ns_attach_object(node, obj_desc, node->type); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -#endif /* ACPI_NO_METHOD_EXECUTION */ - -/******************************************************************************* - * - * FUNCTION: acpi_ds_init_object_from_op - * - * PARAMETERS: walk_state - Current walk state - * Op - Parser op used to init the internal object - * Opcode - AML opcode associated with the object - * ret_obj_desc - Namespace object to be initialized - * - * RETURN: Status - * - * DESCRIPTION: Initialize a namespace object from a parser Op and its - * associated arguments. The namespace object is a more compact - * representation of the Op and its arguments. - * - ******************************************************************************/ - -acpi_status -acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, - u16 opcode, - union acpi_operand_object **ret_obj_desc) -{ - const struct acpi_opcode_info *op_info; - union acpi_operand_object *obj_desc; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ds_init_object_from_op); - - obj_desc = *ret_obj_desc; - op_info = acpi_ps_get_opcode_info(opcode); - if (op_info->class == AML_CLASS_UNKNOWN) { - - /* Unknown opcode */ - - return_ACPI_STATUS(AE_TYPE); - } - - /* Perform per-object initialization */ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_BUFFER: - - /* - * Defer evaluation of Buffer term_arg operand - */ - obj_desc->buffer.node = - ACPI_CAST_PTR(struct acpi_namespace_node, - walk_state->operands[0]); - obj_desc->buffer.aml_start = op->named.data; - obj_desc->buffer.aml_length = op->named.length; - break; - - case ACPI_TYPE_PACKAGE: - - /* - * Defer evaluation of Package term_arg operand - */ - obj_desc->package.node = - ACPI_CAST_PTR(struct acpi_namespace_node, - walk_state->operands[0]); - obj_desc->package.aml_start = op->named.data; - obj_desc->package.aml_length = op->named.length; - break; - - case ACPI_TYPE_INTEGER: - - switch (op_info->type) { - case AML_TYPE_CONSTANT: - /* - * Resolve AML Constants here - AND ONLY HERE! - * All constants are integers. - * We mark the integer with a flag that indicates that it started - * life as a constant -- so that stores to constants will perform - * as expected (noop). zero_op is used as a placeholder for optional - * target operands. - */ - obj_desc->common.flags = AOPOBJ_AML_CONSTANT; - - switch (opcode) { - case AML_ZERO_OP: - - obj_desc->integer.value = 0; - break; - - case AML_ONE_OP: - - obj_desc->integer.value = 1; - break; - - case AML_ONES_OP: - - obj_desc->integer.value = ACPI_INTEGER_MAX; - - /* Truncate value if we are executing from a 32-bit ACPI table */ - -#ifndef ACPI_NO_METHOD_EXECUTION - acpi_ex_truncate_for32bit_table(obj_desc); -#endif - break; - - case AML_REVISION_OP: - - obj_desc->integer.value = ACPI_CA_VERSION; - break; - - default: - - ACPI_ERROR((AE_INFO, - "Unknown constant opcode %X", - opcode)); - status = AE_AML_OPERAND_TYPE; - break; - } - break; - - case AML_TYPE_LITERAL: - - obj_desc->integer.value = op->common.value.integer; -#ifndef ACPI_NO_METHOD_EXECUTION - acpi_ex_truncate_for32bit_table(obj_desc); -#endif - break; - - default: - ACPI_ERROR((AE_INFO, "Unknown Integer type %X", - op_info->type)); - status = AE_AML_OPERAND_TYPE; - break; - } - break; - - case ACPI_TYPE_STRING: - - obj_desc->string.pointer = op->common.value.string; - obj_desc->string.length = - (u32) ACPI_STRLEN(op->common.value.string); - - /* - * The string is contained in the ACPI table, don't ever try - * to delete it - */ - obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; - break; - - case ACPI_TYPE_METHOD: - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - - switch (op_info->type) { - case AML_TYPE_LOCAL_VARIABLE: - - /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */ - - obj_desc->reference.value = opcode - AML_LOCAL_OP; - obj_desc->reference.class = ACPI_REFCLASS_LOCAL; - -#ifndef ACPI_NO_METHOD_EXECUTION - status = - acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL, - obj_desc->reference. - value, walk_state, - ACPI_CAST_INDIRECT_PTR - (struct - acpi_namespace_node, - &obj_desc->reference. - object)); -#endif - break; - - case AML_TYPE_METHOD_ARGUMENT: - - /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */ - - obj_desc->reference.value = opcode - AML_ARG_OP; - obj_desc->reference.class = ACPI_REFCLASS_ARG; - -#ifndef ACPI_NO_METHOD_EXECUTION - status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG, - obj_desc-> - reference.value, - walk_state, - ACPI_CAST_INDIRECT_PTR - (struct - acpi_namespace_node, - &obj_desc-> - reference. - object)); -#endif - break; - - default: /* Object name or Debug object */ - - switch (op->common.aml_opcode) { - case AML_INT_NAMEPATH_OP: - - /* Node was saved in Op */ - - obj_desc->reference.node = op->common.node; - obj_desc->reference.object = - op->common.node->object; - obj_desc->reference.class = ACPI_REFCLASS_NAME; - break; - - case AML_DEBUG_OP: - - obj_desc->reference.class = ACPI_REFCLASS_DEBUG; - break; - - default: - - ACPI_ERROR((AE_INFO, - "Unimplemented reference type for AML opcode: %4.4X", - opcode)); - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - break; - } - break; - - default: - - ACPI_ERROR((AE_INFO, "Unimplemented data type: %X", - ACPI_GET_OBJECT_TYPE(obj_desc))); - - status = AE_AML_OPERAND_TYPE; - break; - } - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c deleted file mode 100644 index cb8a0d3109f0..000000000000 --- a/drivers/acpi/dispatcher/dsopcode.c +++ /dev/null @@ -1,1469 +0,0 @@ -/****************************************************************************** - * - * Module Name: dsopcode - Dispatcher Op Region support and handling of - * "control" opcodes - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_DISPATCHER -ACPI_MODULE_NAME("dsopcode") - -/* Local prototypes */ -static acpi_status -acpi_ds_execute_arguments(struct acpi_namespace_node *node, - struct acpi_namespace_node *scope_node, - u32 aml_length, u8 * aml_start); - -static acpi_status -acpi_ds_init_buffer_field(u16 aml_opcode, - union acpi_operand_object *obj_desc, - union acpi_operand_object *buffer_desc, - union acpi_operand_object *offset_desc, - union acpi_operand_object *length_desc, - union acpi_operand_object *result_desc); - -/******************************************************************************* - * - * FUNCTION: acpi_ds_execute_arguments - * - * PARAMETERS: Node - Object NS node - * scope_node - Parent NS node - * aml_length - Length of executable AML - * aml_start - Pointer to the AML - * - * RETURN: Status. - * - * DESCRIPTION: Late (deferred) execution of region or field arguments - * - ******************************************************************************/ - -static acpi_status -acpi_ds_execute_arguments(struct acpi_namespace_node *node, - struct acpi_namespace_node *scope_node, - u32 aml_length, u8 * aml_start) -{ - acpi_status status; - union acpi_parse_object *op; - struct acpi_walk_state *walk_state; - - ACPI_FUNCTION_TRACE(ds_execute_arguments); - - /* - * Allocate a new parser op to be the root of the parsed tree - */ - op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Save the Node for use in acpi_ps_parse_aml */ - - op->common.node = scope_node; - - /* Create and initialize a new parser state */ - - walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); - if (!walk_state) { - status = AE_NO_MEMORY; - goto cleanup; - } - - status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, - aml_length, NULL, ACPI_IMODE_LOAD_PASS1); - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - goto cleanup; - } - - /* Mark this parse as a deferred opcode */ - - walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; - walk_state->deferred_node = node; - - /* Pass1: Parse the entire declaration */ - - status = acpi_ps_parse_aml(walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Get and init the Op created above */ - - op->common.node = node; - acpi_ps_delete_parse_tree(op); - - /* Evaluate the deferred arguments */ - - op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - op->common.node = scope_node; - - /* Create and initialize a new parser state */ - - walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); - if (!walk_state) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Execute the opcode and arguments */ - - status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, - aml_length, NULL, ACPI_IMODE_EXECUTE); - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - goto cleanup; - } - - /* Mark this execution as a deferred opcode */ - - walk_state->deferred_node = node; - status = acpi_ps_parse_aml(walk_state); - - cleanup: - acpi_ps_delete_parse_tree(op); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_buffer_field_arguments - * - * PARAMETERS: obj_desc - A valid buffer_field object - * - * RETURN: Status. - * - * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late - * evaluation of these field attributes. - * - ******************************************************************************/ - -acpi_status -acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) -{ - union acpi_operand_object *extra_desc; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the AML pointer (method object) and buffer_field node */ - - extra_desc = acpi_ns_get_secondary_object(obj_desc); - node = obj_desc->buffer_field.node; - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_BUFFER_FIELD, node, NULL)); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", - acpi_ut_get_node_name(node))); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), - extra_desc->extra.aml_length, - extra_desc->extra.aml_start); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_bank_field_arguments - * - * PARAMETERS: obj_desc - A valid bank_field object - * - * RETURN: Status. - * - * DESCRIPTION: Get bank_field bank_value. This implements the late - * evaluation of these field attributes. - * - ******************************************************************************/ - -acpi_status -acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) -{ - union acpi_operand_object *extra_desc; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the AML pointer (method object) and bank_field node */ - - extra_desc = acpi_ns_get_secondary_object(obj_desc); - node = obj_desc->bank_field.node; - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", - acpi_ut_get_node_name(node))); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), - extra_desc->extra.aml_length, - extra_desc->extra.aml_start); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_buffer_arguments - * - * PARAMETERS: obj_desc - A valid Buffer object - * - * RETURN: Status. - * - * DESCRIPTION: Get Buffer length and initializer byte list. This implements - * the late evaluation of these attributes. - * - ******************************************************************************/ - -acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) -{ - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the Buffer node */ - - node = obj_desc->buffer.node; - if (!node) { - ACPI_ERROR((AE_INFO, - "No pointer back to NS node in buffer obj %p", - obj_desc)); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, node, - obj_desc->buffer.aml_length, - obj_desc->buffer.aml_start); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_package_arguments - * - * PARAMETERS: obj_desc - A valid Package object - * - * RETURN: Status. - * - * DESCRIPTION: Get Package length and initializer byte list. This implements - * the late evaluation of these attributes. - * - ******************************************************************************/ - -acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) -{ - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the Package node */ - - node = obj_desc->package.node; - if (!node) { - ACPI_ERROR((AE_INFO, - "No pointer back to NS node in package %p", - obj_desc)); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, node, - obj_desc->package.aml_length, - obj_desc->package.aml_start); - return_ACPI_STATUS(status); -} - -/***************************************************************************** - * - * FUNCTION: acpi_ds_get_region_arguments - * - * PARAMETERS: obj_desc - A valid region object - * - * RETURN: Status. - * - * DESCRIPTION: Get region address and length. This implements the late - * evaluation of these region attributes. - * - ****************************************************************************/ - -acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) -{ - struct acpi_namespace_node *node; - acpi_status status; - union acpi_operand_object *extra_desc; - - ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); - - if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - extra_desc = acpi_ns_get_secondary_object(obj_desc); - if (!extra_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* Get the Region node */ - - node = obj_desc->region.node; - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_REGION, node, NULL)); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", - acpi_ut_get_node_name(node), - extra_desc->extra.aml_start)); - - /* Execute the argument AML */ - - status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), - extra_desc->extra.aml_length, - extra_desc->extra.aml_start); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Validate the region address/length via the host OS */ - - status = acpi_os_validate_address(obj_desc->region.space_id, - obj_desc->region.address, - (acpi_size) obj_desc->region.length, - acpi_ut_get_node_name(node)); - - if (ACPI_FAILURE(status)) { - /* - * Invalid address/length. We will emit an error message and mark - * the region as invalid, so that it will cause an additional error if - * it is ever used. Then return AE_OK. - */ - ACPI_EXCEPTION((AE_INFO, status, - "During address validation of OpRegion [%4.4s]", - node->name.ascii)); - obj_desc->common.flags |= AOPOBJ_INVALID; - status = AE_OK; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_initialize_region - * - * PARAMETERS: obj_handle - Region namespace node - * - * RETURN: Status - * - * DESCRIPTION: Front end to ev_initialize_region - * - ******************************************************************************/ - -acpi_status acpi_ds_initialize_region(acpi_handle obj_handle) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - - obj_desc = acpi_ns_get_attached_object(obj_handle); - - /* Namespace is NOT locked */ - - status = acpi_ev_initialize_region(obj_desc, FALSE); - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_init_buffer_field - * - * PARAMETERS: aml_opcode - create_xxx_field - * obj_desc - buffer_field object - * buffer_desc - Host Buffer - * offset_desc - Offset into buffer - * length_desc - Length of field (CREATE_FIELD_OP only) - * result_desc - Where to store the result - * - * RETURN: Status - * - * DESCRIPTION: Perform actual initialization of a buffer field - * - ******************************************************************************/ - -static acpi_status -acpi_ds_init_buffer_field(u16 aml_opcode, - union acpi_operand_object *obj_desc, - union acpi_operand_object *buffer_desc, - union acpi_operand_object *offset_desc, - union acpi_operand_object *length_desc, - union acpi_operand_object *result_desc) -{ - u32 offset; - u32 bit_offset; - u32 bit_count; - u8 field_flags; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc); - - /* Host object must be a Buffer */ - - if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) { - ACPI_ERROR((AE_INFO, - "Target of Create Field is not a Buffer object - %s", - acpi_ut_get_object_type_name(buffer_desc))); - - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - - /* - * The last parameter to all of these opcodes (result_desc) started - * out as a name_string, and should therefore now be a NS node - * after resolution in acpi_ex_resolve_operands(). - */ - if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) { - ACPI_ERROR((AE_INFO, - "(%s) destination not a NS Node [%s]", - acpi_ps_get_opcode_name(aml_opcode), - acpi_ut_get_descriptor_name(result_desc))); - - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - - offset = (u32) offset_desc->integer.value; - - /* - * Setup the Bit offsets and counts, according to the opcode - */ - switch (aml_opcode) { - case AML_CREATE_FIELD_OP: - - /* Offset is in bits, count is in bits */ - - field_flags = AML_FIELD_ACCESS_BYTE; - bit_offset = offset; - bit_count = (u32) length_desc->integer.value; - - /* Must have a valid (>0) bit count */ - - if (bit_count == 0) { - ACPI_ERROR((AE_INFO, - "Attempt to CreateField of length zero")); - status = AE_AML_OPERAND_VALUE; - goto cleanup; - } - break; - - case AML_CREATE_BIT_FIELD_OP: - - /* Offset is in bits, Field is one bit */ - - bit_offset = offset; - bit_count = 1; - field_flags = AML_FIELD_ACCESS_BYTE; - break; - - case AML_CREATE_BYTE_FIELD_OP: - - /* Offset is in bytes, field is one byte */ - - bit_offset = 8 * offset; - bit_count = 8; - field_flags = AML_FIELD_ACCESS_BYTE; - break; - - case AML_CREATE_WORD_FIELD_OP: - - /* Offset is in bytes, field is one word */ - - bit_offset = 8 * offset; - bit_count = 16; - field_flags = AML_FIELD_ACCESS_WORD; - break; - - case AML_CREATE_DWORD_FIELD_OP: - - /* Offset is in bytes, field is one dword */ - - bit_offset = 8 * offset; - bit_count = 32; - field_flags = AML_FIELD_ACCESS_DWORD; - break; - - case AML_CREATE_QWORD_FIELD_OP: - - /* Offset is in bytes, field is one qword */ - - bit_offset = 8 * offset; - bit_count = 64; - field_flags = AML_FIELD_ACCESS_QWORD; - break; - - default: - - ACPI_ERROR((AE_INFO, - "Unknown field creation opcode %02x", aml_opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - /* Entire field must fit within the current length of the buffer */ - - if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) { - ACPI_ERROR((AE_INFO, - "Field [%4.4s] at %d exceeds Buffer [%4.4s] size %d (bits)", - acpi_ut_get_node_name(result_desc), - bit_offset + bit_count, - acpi_ut_get_node_name(buffer_desc->buffer.node), - 8 * (u32) buffer_desc->buffer.length)); - status = AE_AML_BUFFER_LIMIT; - goto cleanup; - } - - /* - * Initialize areas of the field object that are common to all fields - * For field_flags, use LOCK_RULE = 0 (NO_LOCK), - * UPDATE_RULE = 0 (UPDATE_PRESERVE) - */ - status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0, - bit_offset, bit_count); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - obj_desc->buffer_field.buffer_obj = buffer_desc; - - /* Reference count for buffer_desc inherits obj_desc count */ - - buffer_desc->common.reference_count = (u16) - (buffer_desc->common.reference_count + - obj_desc->common.reference_count); - - cleanup: - - /* Always delete the operands */ - - acpi_ut_remove_reference(offset_desc); - acpi_ut_remove_reference(buffer_desc); - - if (aml_opcode == AML_CREATE_FIELD_OP) { - acpi_ut_remove_reference(length_desc); - } - - /* On failure, delete the result descriptor */ - - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(result_desc); /* Result descriptor */ - } else { - /* Now the address and length are valid for this buffer_field */ - - obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_eval_buffer_field_operands - * - * PARAMETERS: walk_state - Current walk - * Op - A valid buffer_field Op object - * - * RETURN: Status - * - * DESCRIPTION: Get buffer_field Buffer and Index - * Called from acpi_ds_exec_end_op during buffer_field parse tree walk - * - ******************************************************************************/ - -acpi_status -acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, - union acpi_parse_object *op) -{ - acpi_status status; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - union acpi_parse_object *next_op; - - ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op); - - /* - * This is where we evaluate the address and length fields of the - * create_xxx_field declaration - */ - node = op->common.node; - - /* next_op points to the op that holds the Buffer */ - - next_op = op->common.value.arg; - - /* Evaluate/create the address and length operands */ - - status = acpi_ds_create_operands(walk_state, next_op); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* Resolve the operands */ - - status = acpi_ex_resolve_operands(op->common.aml_opcode, - ACPI_WALK_OPERANDS, walk_state); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)", - acpi_ps_get_opcode_name(op->common.aml_opcode), - status)); - - return_ACPI_STATUS(status); - } - - /* Initialize the Buffer Field */ - - if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { - - /* NOTE: Slightly different operands for this opcode */ - - status = - acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, - walk_state->operands[0], - walk_state->operands[1], - walk_state->operands[2], - walk_state->operands[3]); - } else { - /* All other, create_xxx_field opcodes */ - - status = - acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, - walk_state->operands[0], - walk_state->operands[1], NULL, - walk_state->operands[2]); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_eval_region_operands - * - * PARAMETERS: walk_state - Current walk - * Op - A valid region Op object - * - * RETURN: Status - * - * DESCRIPTION: Get region address and length - * Called from acpi_ds_exec_end_op during op_region parse tree walk - * - ******************************************************************************/ - -acpi_status -acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, - union acpi_parse_object *op) -{ - acpi_status status; - union acpi_operand_object *obj_desc; - union acpi_operand_object *operand_desc; - struct acpi_namespace_node *node; - union acpi_parse_object *next_op; - - ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op); - - /* - * This is where we evaluate the address and length fields of the - * op_region declaration - */ - node = op->common.node; - - /* next_op points to the op that holds the space_iD */ - - next_op = op->common.value.arg; - - /* next_op points to address op */ - - next_op = next_op->common.next; - - /* Evaluate/create the address and length operands */ - - status = acpi_ds_create_operands(walk_state, next_op); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Resolve the length and address operands to numbers */ - - status = acpi_ex_resolve_operands(op->common.aml_opcode, - ACPI_WALK_OPERANDS, walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* - * Get the length operand and save it - * (at Top of stack) - */ - operand_desc = walk_state->operands[walk_state->num_operands - 1]; - - obj_desc->region.length = (u32) operand_desc->integer.value; - acpi_ut_remove_reference(operand_desc); - - /* - * Get the address and save it - * (at top of stack - 1) - */ - operand_desc = walk_state->operands[walk_state->num_operands - 2]; - - obj_desc->region.address = (acpi_physical_address) - operand_desc->integer.value; - acpi_ut_remove_reference(operand_desc); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", - obj_desc, - ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), - obj_desc->region.length)); - - /* Now the address and length are valid for this opregion */ - - obj_desc->region.flags |= AOPOBJ_DATA_VALID; - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_eval_table_region_operands - * - * PARAMETERS: walk_state - Current walk - * Op - A valid region Op object - * - * RETURN: Status - * - * DESCRIPTION: Get region address and length - * Called from acpi_ds_exec_end_op during data_table_region parse tree walk - * - ******************************************************************************/ - -acpi_status -acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, - union acpi_parse_object *op) -{ - acpi_status status; - union acpi_operand_object *obj_desc; - union acpi_operand_object **operand; - struct acpi_namespace_node *node; - union acpi_parse_object *next_op; - u32 table_index; - struct acpi_table_header *table; - - ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); - - /* - * This is where we evaluate the signature_string and oem_iDString - * and oem_table_iDString of the data_table_region declaration - */ - node = op->common.node; - - /* next_op points to signature_string op */ - - next_op = op->common.value.arg; - - /* - * Evaluate/create the signature_string and oem_iDString - * and oem_table_iDString operands - */ - status = acpi_ds_create_operands(walk_state, next_op); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Resolve the signature_string and oem_iDString - * and oem_table_iDString operands - */ - status = acpi_ex_resolve_operands(op->common.aml_opcode, - ACPI_WALK_OPERANDS, walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - operand = &walk_state->operands[0]; - - /* Find the ACPI table */ - - status = acpi_tb_find_table(operand[0]->string.pointer, - operand[1]->string.pointer, - operand[2]->string.pointer, &table_index); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - acpi_ut_remove_reference(operand[0]); - acpi_ut_remove_reference(operand[1]); - acpi_ut_remove_reference(operand[2]); - - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - obj_desc->region.address = - (acpi_physical_address) ACPI_TO_INTEGER(table); - obj_desc->region.length = table->length; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", - obj_desc, - ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), - obj_desc->region.length)); - - /* Now the address and length are valid for this opregion */ - - obj_desc->region.flags |= AOPOBJ_DATA_VALID; - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_eval_data_object_operands - * - * PARAMETERS: walk_state - Current walk - * Op - A valid data_object Op object - * obj_desc - data_object - * - * RETURN: Status - * - * DESCRIPTION: Get the operands and complete the following data object types: - * Buffer, Package. - * - ******************************************************************************/ - -acpi_status -acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, - union acpi_operand_object *obj_desc) -{ - acpi_status status; - union acpi_operand_object *arg_desc; - u32 length; - - ACPI_FUNCTION_TRACE(ds_eval_data_object_operands); - - /* The first operand (for all of these data objects) is the length */ - - /* - * Set proper index into operand stack for acpi_ds_obj_stack_push - * invoked inside acpi_ds_create_operand. - */ - walk_state->operand_index = walk_state->num_operands; - - status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_ex_resolve_operands(walk_state->opcode, - &(walk_state-> - operands[walk_state->num_operands - - 1]), walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Extract length operand */ - - arg_desc = walk_state->operands[walk_state->num_operands - 1]; - length = (u32) arg_desc->integer.value; - - /* Cleanup for length operand */ - - status = acpi_ds_obj_stack_pop(1, walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - acpi_ut_remove_reference(arg_desc); - - /* - * Create the actual data object - */ - switch (op->common.aml_opcode) { - case AML_BUFFER_OP: - - status = - acpi_ds_build_internal_buffer_obj(walk_state, op, length, - &obj_desc); - break; - - case AML_PACKAGE_OP: - case AML_VAR_PACKAGE_OP: - - status = - acpi_ds_build_internal_package_obj(walk_state, op, length, - &obj_desc); - break; - - default: - return_ACPI_STATUS(AE_AML_BAD_OPCODE); - } - - if (ACPI_SUCCESS(status)) { - /* - * Return the object in the walk_state, unless the parent is a package - - * in this case, the return object will be stored in the parse tree - * for the package. - */ - if ((!op->common.parent) || - ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && - (op->common.parent->common.aml_opcode != - AML_VAR_PACKAGE_OP) - && (op->common.parent->common.aml_opcode != AML_NAME_OP))) { - walk_state->result_obj = obj_desc; - } - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_eval_bank_field_operands - * - * PARAMETERS: walk_state - Current walk - * Op - A valid bank_field Op object - * - * RETURN: Status - * - * DESCRIPTION: Get bank_field bank_value - * Called from acpi_ds_exec_end_op during bank_field parse tree walk - * - ******************************************************************************/ - -acpi_status -acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, - union acpi_parse_object *op) -{ - acpi_status status; - union acpi_operand_object *obj_desc; - union acpi_operand_object *operand_desc; - struct acpi_namespace_node *node; - union acpi_parse_object *next_op; - union acpi_parse_object *arg; - - ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); - - /* - * This is where we evaluate the bank_value field of the - * bank_field declaration - */ - - /* next_op points to the op that holds the Region */ - - next_op = op->common.value.arg; - - /* next_op points to the op that holds the Bank Register */ - - next_op = next_op->common.next; - - /* next_op points to the op that holds the Bank Value */ - - next_op = next_op->common.next; - - /* - * Set proper index into operand stack for acpi_ds_obj_stack_push - * invoked inside acpi_ds_create_operand. - * - * We use walk_state->Operands[0] to store the evaluated bank_value - */ - walk_state->operand_index = 0; - - status = acpi_ds_create_operand(walk_state, next_op, 0); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, - acpi_ps_get_opcode_name(op->common.aml_opcode), 1); - /* - * Get the bank_value operand and save it - * (at Top of stack) - */ - operand_desc = walk_state->operands[0]; - - /* Arg points to the start Bank Field */ - - arg = acpi_ps_get_arg(op, 4); - while (arg) { - - /* Ignore OFFSET and ACCESSAS terms here */ - - if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { - node = arg->common.node; - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - obj_desc->bank_field.value = - (u32) operand_desc->integer.value; - } - - /* Move to next field in the list */ - - arg = arg->common.next; - } - - acpi_ut_remove_reference(operand_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_exec_begin_control_op - * - * PARAMETERS: walk_list - The list that owns the walk stack - * Op - The control Op - * - * RETURN: Status - * - * DESCRIPTION: Handles all control ops encountered during control method - * execution. - * - ******************************************************************************/ - -acpi_status -acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op) -{ - acpi_status status = AE_OK; - union acpi_generic_state *control_state; - - ACPI_FUNCTION_NAME(ds_exec_begin_control_op); - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, - op->common.aml_opcode, walk_state)); - - switch (op->common.aml_opcode) { - case AML_WHILE_OP: - - /* - * If this is an additional iteration of a while loop, continue. - * There is no need to allocate a new control state. - */ - if (walk_state->control_state) { - if (walk_state->control_state->control.aml_predicate_start - == (walk_state->parser_state.aml - 1)) { - - /* Reset the state to start-of-loop */ - - walk_state->control_state->common.state = - ACPI_CONTROL_CONDITIONAL_EXECUTING; - break; - } - } - - /*lint -fallthrough */ - - case AML_IF_OP: - - /* - * IF/WHILE: Create a new control state to manage these - * constructs. We need to manage these as a stack, in order - * to handle nesting. - */ - control_state = acpi_ut_create_control_state(); - if (!control_state) { - status = AE_NO_MEMORY; - break; - } - /* - * Save a pointer to the predicate for multiple executions - * of a loop - */ - control_state->control.aml_predicate_start = - walk_state->parser_state.aml - 1; - control_state->control.package_end = - walk_state->parser_state.pkg_end; - control_state->control.opcode = op->common.aml_opcode; - - /* Push the control state on this walk's control stack */ - - acpi_ut_push_generic_state(&walk_state->control_state, - control_state); - break; - - case AML_ELSE_OP: - - /* Predicate is in the state object */ - /* If predicate is true, the IF was executed, ignore ELSE part */ - - if (walk_state->last_predicate) { - status = AE_CTRL_TRUE; - } - - break; - - case AML_RETURN_OP: - - break; - - default: - break; - } - - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_exec_end_control_op - * - * PARAMETERS: walk_list - The list that owns the walk stack - * Op - The control Op - * - * RETURN: Status - * - * DESCRIPTION: Handles all control ops encountered during control method - * execution. - * - ******************************************************************************/ - -acpi_status -acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, - union acpi_parse_object * op) -{ - acpi_status status = AE_OK; - union acpi_generic_state *control_state; - - ACPI_FUNCTION_NAME(ds_exec_end_control_op); - - switch (op->common.aml_opcode) { - case AML_IF_OP: - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); - - /* - * Save the result of the predicate in case there is an - * ELSE to come - */ - walk_state->last_predicate = - (u8) walk_state->control_state->common.value; - - /* - * Pop the control state that was created at the start - * of the IF and free it - */ - control_state = - acpi_ut_pop_generic_state(&walk_state->control_state); - acpi_ut_delete_generic_state(control_state); - break; - - case AML_ELSE_OP: - - break; - - case AML_WHILE_OP: - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); - - control_state = walk_state->control_state; - if (control_state->common.value) { - - /* Predicate was true, the body of the loop was just executed */ - - /* - * This loop counter mechanism allows the interpreter to escape - * possibly infinite loops. This can occur in poorly written AML - * when the hardware does not respond within a while loop and the - * loop does not implement a timeout. - */ - control_state->control.loop_count++; - if (control_state->control.loop_count > - ACPI_MAX_LOOP_ITERATIONS) { - status = AE_AML_INFINITE_LOOP; - break; - } - - /* - * Go back and evaluate the predicate and maybe execute the loop - * another time - */ - status = AE_CTRL_PENDING; - walk_state->aml_last_while = - control_state->control.aml_predicate_start; - break; - } - - /* Predicate was false, terminate this while loop */ - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "[WHILE_OP] termination! Op=%p\n", op)); - - /* Pop this control state and free it */ - - control_state = - acpi_ut_pop_generic_state(&walk_state->control_state); - acpi_ut_delete_generic_state(control_state); - break; - - case AML_RETURN_OP: - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "[RETURN_OP] Op=%p Arg=%p\n", op, - op->common.value.arg)); - - /* - * One optional operand -- the return value - * It can be either an immediate operand or a result that - * has been bubbled up the tree - */ - if (op->common.value.arg) { - - /* Since we have a real Return(), delete any implicit return */ - - acpi_ds_clear_implicit_return(walk_state); - - /* Return statement has an immediate operand */ - - status = - acpi_ds_create_operands(walk_state, - op->common.value.arg); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * If value being returned is a Reference (such as - * an arg or local), resolve it now because it may - * cease to exist at the end of the method. - */ - status = - acpi_ex_resolve_to_value(&walk_state->operands[0], - walk_state); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Get the return value and save as the last result - * value. This is the only place where walk_state->return_desc - * is set to anything other than zero! - */ - walk_state->return_desc = walk_state->operands[0]; - } else if (walk_state->result_count) { - - /* Since we have a real Return(), delete any implicit return */ - - acpi_ds_clear_implicit_return(walk_state); - - /* - * The return value has come from a previous calculation. - * - * If value being returned is a Reference (such as - * an arg or local), resolve it now because it may - * cease to exist at the end of the method. - * - * Allow references created by the Index operator to return unchanged. - */ - if ((ACPI_GET_DESCRIPTOR_TYPE - (walk_state->results->results.obj_desc[0]) == - ACPI_DESC_TYPE_OPERAND) - && - (ACPI_GET_OBJECT_TYPE - (walk_state->results->results.obj_desc[0]) == - ACPI_TYPE_LOCAL_REFERENCE) - && ((walk_state->results->results.obj_desc[0])-> - reference.class != ACPI_REFCLASS_INDEX)) { - status = - acpi_ex_resolve_to_value(&walk_state-> - results->results. - obj_desc[0], - walk_state); - if (ACPI_FAILURE(status)) { - return (status); - } - } - - walk_state->return_desc = - walk_state->results->results.obj_desc[0]; - } else { - /* No return operand */ - - if (walk_state->num_operands) { - acpi_ut_remove_reference(walk_state-> - operands[0]); - } - - walk_state->operands[0] = NULL; - walk_state->num_operands = 0; - walk_state->return_desc = NULL; - } - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Completed RETURN_OP State=%p, RetVal=%p\n", - walk_state, walk_state->return_desc)); - - /* End the control method execution right now */ - - status = AE_CTRL_TERMINATE; - break; - - case AML_NOOP_OP: - - /* Just do nothing! */ - break; - - case AML_BREAK_POINT_OP: - - /* Call up to the OS service layer to handle this */ - - status = - acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, - "Executed AML Breakpoint opcode"); - - /* If and when it returns, all done. */ - - break; - - case AML_BREAK_OP: - case AML_CONTINUE_OP: /* ACPI 2.0 */ - - /* Pop and delete control states until we find a while */ - - while (walk_state->control_state && - (walk_state->control_state->control.opcode != - AML_WHILE_OP)) { - control_state = - acpi_ut_pop_generic_state(&walk_state-> - control_state); - acpi_ut_delete_generic_state(control_state); - } - - /* No while found? */ - - if (!walk_state->control_state) { - return (AE_AML_NO_WHILE); - } - - /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ - - walk_state->aml_last_while = - walk_state->control_state->control.package_end; - - /* Return status depending on opcode */ - - if (op->common.aml_opcode == AML_BREAK_OP) { - status = AE_CTRL_BREAK; - } else { - status = AE_CTRL_CONTINUE; - } - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p", - op->common.aml_opcode, op)); - - status = AE_AML_BAD_OPCODE; - break; - } - - return (status); -} diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c deleted file mode 100644 index 9c88846ca2ce..000000000000 --- a/drivers/acpi/dispatcher/dsutils.c +++ /dev/null @@ -1,869 +0,0 @@ -/******************************************************************************* - * - * Module Name: dsutils - Dispatcher utilities - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_DISPATCHER -ACPI_MODULE_NAME("dsutils") - -/******************************************************************************* - * - * FUNCTION: acpi_ds_clear_implicit_return - * - * PARAMETERS: walk_state - Current State - * - * RETURN: None. - * - * DESCRIPTION: Clear and remove a reference on an implicit return value. Used - * to delete "stale" return values (if enabled, the return value - * from every operator is saved at least momentarily, in case the - * parent method exits.) - * - ******************************************************************************/ -void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state) -{ - ACPI_FUNCTION_NAME(ds_clear_implicit_return); - - /* - * Slack must be enabled for this feature - */ - if (!acpi_gbl_enable_interpreter_slack) { - return; - } - - if (walk_state->implicit_return_obj) { - /* - * Delete any "stale" implicit return. However, in - * complex statements, the implicit return value can be - * bubbled up several levels. - */ - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Removing reference on stale implicit return obj %p\n", - walk_state->implicit_return_obj)); - - acpi_ut_remove_reference(walk_state->implicit_return_obj); - walk_state->implicit_return_obj = NULL; - } -} - -#ifndef ACPI_NO_METHOD_EXECUTION -/******************************************************************************* - * - * FUNCTION: acpi_ds_do_implicit_return - * - * PARAMETERS: return_desc - The return value - * walk_state - Current State - * add_reference - True if a reference should be added to the - * return object - * - * RETURN: TRUE if implicit return enabled, FALSE otherwise - * - * DESCRIPTION: Implements the optional "implicit return". We save the result - * of every ASL operator and control method invocation in case the - * parent method exit. Before storing a new return value, we - * delete the previous return value. - * - ******************************************************************************/ - -u8 -acpi_ds_do_implicit_return(union acpi_operand_object *return_desc, - struct acpi_walk_state *walk_state, u8 add_reference) -{ - ACPI_FUNCTION_NAME(ds_do_implicit_return); - - /* - * Slack must be enabled for this feature, and we must - * have a valid return object - */ - if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) { - return (FALSE); - } - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Result %p will be implicitly returned; Prev=%p\n", - return_desc, walk_state->implicit_return_obj)); - - /* - * Delete any "stale" implicit return value first. However, in - * complex statements, the implicit return value can be - * bubbled up several levels, so we don't clear the value if it - * is the same as the return_desc. - */ - if (walk_state->implicit_return_obj) { - if (walk_state->implicit_return_obj == return_desc) { - return (TRUE); - } - acpi_ds_clear_implicit_return(walk_state); - } - - /* Save the implicit return value, add a reference if requested */ - - walk_state->implicit_return_obj = return_desc; - if (add_reference) { - acpi_ut_add_reference(return_desc); - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_is_result_used - * - * PARAMETERS: Op - Current Op - * walk_state - Current State - * - * RETURN: TRUE if result is used, FALSE otherwise - * - * DESCRIPTION: Check if a result object will be used by the parent - * - ******************************************************************************/ - -u8 -acpi_ds_is_result_used(union acpi_parse_object * op, - struct acpi_walk_state * walk_state) -{ - const struct acpi_opcode_info *parent_info; - - ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op); - - /* Must have both an Op and a Result Object */ - - if (!op) { - ACPI_ERROR((AE_INFO, "Null Op")); - return_UINT8(TRUE); - } - - /* - * We know that this operator is not a - * Return() operator (would not come here.) The following code is the - * optional support for a so-called "implicit return". Some AML code - * assumes that the last value of the method is "implicitly" returned - * to the caller. Just save the last result as the return value. - * NOTE: this is optional because the ASL language does not actually - * support this behavior. - */ - (void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state, - TRUE); - - /* - * Now determine if the parent will use the result - * - * If there is no parent, or the parent is a scope_op, we are executing - * at the method level. An executing method typically has no parent, - * since each method is parsed separately. A method invoked externally - * via execute_control_method has a scope_op as the parent. - */ - if ((!op->common.parent) || - (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) { - - /* No parent, the return value cannot possibly be used */ - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "At Method level, result of [%s] not used\n", - acpi_ps_get_opcode_name(op->common. - aml_opcode))); - return_UINT8(FALSE); - } - - /* Get info on the parent. The root_op is AML_SCOPE */ - - parent_info = - acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode); - if (parent_info->class == AML_CLASS_UNKNOWN) { - ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op)); - return_UINT8(FALSE); - } - - /* - * Decide what to do with the result based on the parent. If - * the parent opcode will not use the result, delete the object. - * Otherwise leave it as is, it will be deleted when it is used - * as an operand later. - */ - switch (parent_info->class) { - case AML_CLASS_CONTROL: - - switch (op->common.parent->common.aml_opcode) { - case AML_RETURN_OP: - - /* Never delete the return value associated with a return opcode */ - - goto result_used; - - case AML_IF_OP: - case AML_WHILE_OP: - - /* - * If we are executing the predicate AND this is the predicate op, - * we will use the return value - */ - if ((walk_state->control_state->common.state == - ACPI_CONTROL_PREDICATE_EXECUTING) - && (walk_state->control_state->control. - predicate_op == op)) { - goto result_used; - } - break; - - default: - /* Ignore other control opcodes */ - break; - } - - /* The general control opcode returns no result */ - - goto result_not_used; - - case AML_CLASS_CREATE: - - /* - * These opcodes allow term_arg(s) as operands and therefore - * the operands can be method calls. The result is used. - */ - goto result_used; - - case AML_CLASS_NAMED_OBJECT: - - if ((op->common.parent->common.aml_opcode == AML_REGION_OP) || - (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) - || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) - || (op->common.parent->common.aml_opcode == - AML_VAR_PACKAGE_OP) - || (op->common.parent->common.aml_opcode == AML_BUFFER_OP) - || (op->common.parent->common.aml_opcode == - AML_INT_EVAL_SUBTREE_OP) - || (op->common.parent->common.aml_opcode == - AML_BANK_FIELD_OP)) { - /* - * These opcodes allow term_arg(s) as operands and therefore - * the operands can be method calls. The result is used. - */ - goto result_used; - } - - goto result_not_used; - - default: - - /* - * In all other cases. the parent will actually use the return - * object, so keep it. - */ - goto result_used; - } - - result_used: - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Result of [%s] used by Parent [%s] Op=%p\n", - acpi_ps_get_opcode_name(op->common.aml_opcode), - acpi_ps_get_opcode_name(op->common.parent->common. - aml_opcode), op)); - - return_UINT8(TRUE); - - result_not_used: - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Result of [%s] not used by Parent [%s] Op=%p\n", - acpi_ps_get_opcode_name(op->common.aml_opcode), - acpi_ps_get_opcode_name(op->common.parent->common. - aml_opcode), op)); - - return_UINT8(FALSE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_delete_result_if_not_used - * - * PARAMETERS: Op - Current parse Op - * result_obj - Result of the operation - * walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Used after interpretation of an opcode. If there is an internal - * result descriptor, check if the parent opcode will actually use - * this result. If not, delete the result now so that it will - * not become orphaned. - * - ******************************************************************************/ - -void -acpi_ds_delete_result_if_not_used(union acpi_parse_object *op, - union acpi_operand_object *result_obj, - struct acpi_walk_state *walk_state) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj); - - if (!op) { - ACPI_ERROR((AE_INFO, "Null Op")); - return_VOID; - } - - if (!result_obj) { - return_VOID; - } - - if (!acpi_ds_is_result_used(op, walk_state)) { - - /* Must pop the result stack (obj_desc should be equal to result_obj) */ - - status = acpi_ds_result_pop(&obj_desc, walk_state); - if (ACPI_SUCCESS(status)) { - acpi_ut_remove_reference(result_obj); - } - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_resolve_operands - * - * PARAMETERS: walk_state - Current walk state with operands on stack - * - * RETURN: Status - * - * DESCRIPTION: Resolve all operands to their values. Used to prepare - * arguments to a control method invocation (a call from one - * method to another.) - * - ******************************************************************************/ - -acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state) -{ - u32 i; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state); - - /* - * Attempt to resolve each of the valid operands - * Method arguments are passed by reference, not by value. This means - * that the actual objects are passed, not copies of the objects. - */ - for (i = 0; i < walk_state->num_operands; i++) { - status = - acpi_ex_resolve_to_value(&walk_state->operands[i], - walk_state); - if (ACPI_FAILURE(status)) { - break; - } - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_clear_operands - * - * PARAMETERS: walk_state - Current walk state with operands on stack - * - * RETURN: None - * - * DESCRIPTION: Clear all operands on the current walk state operand stack. - * - ******************************************************************************/ - -void acpi_ds_clear_operands(struct acpi_walk_state *walk_state) -{ - u32 i; - - ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state); - - /* Remove a reference on each operand on the stack */ - - for (i = 0; i < walk_state->num_operands; i++) { - /* - * Remove a reference to all operands, including both - * "Arguments" and "Targets". - */ - acpi_ut_remove_reference(walk_state->operands[i]); - walk_state->operands[i] = NULL; - } - - walk_state->num_operands = 0; - return_VOID; -} -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ds_create_operand - * - * PARAMETERS: walk_state - Current walk state - * Arg - Parse object for the argument - * arg_index - Which argument (zero based) - * - * RETURN: Status - * - * DESCRIPTION: Translate a parse tree object that is an argument to an AML - * opcode to the equivalent interpreter object. This may include - * looking up a name or entering a new name into the internal - * namespace. - * - ******************************************************************************/ - -acpi_status -acpi_ds_create_operand(struct acpi_walk_state *walk_state, - union acpi_parse_object *arg, u32 arg_index) -{ - acpi_status status = AE_OK; - char *name_string; - u32 name_length; - union acpi_operand_object *obj_desc; - union acpi_parse_object *parent_op; - u16 opcode; - acpi_interpreter_mode interpreter_mode; - const struct acpi_opcode_info *op_info; - - ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg); - - /* A valid name must be looked up in the namespace */ - - if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && - (arg->common.value.string) && - !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", - arg)); - - /* Get the entire name string from the AML stream */ - - status = - acpi_ex_get_name_string(ACPI_TYPE_ANY, - arg->common.value.buffer, - &name_string, &name_length); - - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* All prefixes have been handled, and the name is in name_string */ - - /* - * Special handling for buffer_field declarations. This is a deferred - * opcode that unfortunately defines the field name as the last - * parameter instead of the first. We get here when we are performing - * the deferred execution, so the actual name of the field is already - * in the namespace. We don't want to attempt to look it up again - * because we may be executing in a different scope than where the - * actual opcode exists. - */ - if ((walk_state->deferred_node) && - (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) - && (arg_index == - (u32) ((walk_state->opcode == - AML_CREATE_FIELD_OP) ? 3 : 2))) { - obj_desc = - ACPI_CAST_PTR(union acpi_operand_object, - walk_state->deferred_node); - status = AE_OK; - } else { /* All other opcodes */ - - /* - * Differentiate between a namespace "create" operation - * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. - * IMODE_EXECUTE) in order to support the creation of - * namespace objects during the execution of control methods. - */ - parent_op = arg->common.parent; - op_info = - acpi_ps_get_opcode_info(parent_op->common. - aml_opcode); - if ((op_info->flags & AML_NSNODE) - && (parent_op->common.aml_opcode != - AML_INT_METHODCALL_OP) - && (parent_op->common.aml_opcode != AML_REGION_OP) - && (parent_op->common.aml_opcode != - AML_INT_NAMEPATH_OP)) { - - /* Enter name into namespace if not found */ - - interpreter_mode = ACPI_IMODE_LOAD_PASS2; - } else { - /* Return a failure if name not found */ - - interpreter_mode = ACPI_IMODE_EXECUTE; - } - - status = - acpi_ns_lookup(walk_state->scope_info, name_string, - ACPI_TYPE_ANY, interpreter_mode, - ACPI_NS_SEARCH_PARENT | - ACPI_NS_DONT_OPEN_SCOPE, walk_state, - ACPI_CAST_INDIRECT_PTR(struct - acpi_namespace_node, - &obj_desc)); - /* - * The only case where we pass through (ignore) a NOT_FOUND - * error is for the cond_ref_of opcode. - */ - if (status == AE_NOT_FOUND) { - if (parent_op->common.aml_opcode == - AML_COND_REF_OF_OP) { - /* - * For the Conditional Reference op, it's OK if - * the name is not found; We just need a way to - * indicate this to the interpreter, set the - * object to the root - */ - obj_desc = ACPI_CAST_PTR(union - acpi_operand_object, - acpi_gbl_root_node); - status = AE_OK; - } else { - /* - * We just plain didn't find it -- which is a - * very serious error at this point - */ - status = AE_AML_NAME_NOT_FOUND; - } - } - - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(name_string, status); - } - } - - /* Free the namestring created above */ - - ACPI_FREE(name_string); - - /* Check status from the lookup */ - - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Put the resulting object onto the current object stack */ - - status = acpi_ds_obj_stack_push(obj_desc, walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object - (obj_desc, walk_state)); - } else { - /* Check for null name case */ - - if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && - !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { - /* - * If the name is null, this means that this is an - * optional result parameter that was not specified - * in the original ASL. Create a Zero Constant for a - * placeholder. (Store to a constant is a Noop.) - */ - opcode = AML_ZERO_OP; /* Has no arguments! */ - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Null namepath: Arg=%p\n", arg)); - } else { - opcode = arg->common.aml_opcode; - } - - /* Get the object type of the argument */ - - op_info = acpi_ps_get_opcode_info(opcode); - if (op_info->object_type == ACPI_TYPE_INVALID) { - return_ACPI_STATUS(AE_NOT_IMPLEMENTED); - } - - if ((op_info->flags & AML_HAS_RETVAL) - || (arg->common.flags & ACPI_PARSEOP_IN_STACK)) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Argument previously created, already stacked\n")); - - ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object - (walk_state-> - operands[walk_state->num_operands - - 1], walk_state)); - - /* - * Use value that was already previously returned - * by the evaluation of this argument - */ - status = acpi_ds_result_pop(&obj_desc, walk_state); - if (ACPI_FAILURE(status)) { - /* - * Only error is underflow, and this indicates - * a missing or null operand! - */ - ACPI_EXCEPTION((AE_INFO, status, - "Missing or null operand")); - return_ACPI_STATUS(status); - } - } else { - /* Create an ACPI_INTERNAL_OBJECT for the argument */ - - obj_desc = - acpi_ut_create_internal_object(op_info-> - object_type); - if (!obj_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Initialize the new object */ - - status = - acpi_ds_init_object_from_op(walk_state, arg, opcode, - &obj_desc); - if (ACPI_FAILURE(status)) { - acpi_ut_delete_object_desc(obj_desc); - return_ACPI_STATUS(status); - } - } - - /* Put the operand object on the object stack */ - - status = acpi_ds_obj_stack_push(obj_desc, walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object - (obj_desc, walk_state)); - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_create_operands - * - * PARAMETERS: walk_state - Current state - * first_arg - First argument of a parser argument tree - * - * RETURN: Status - * - * DESCRIPTION: Convert an operator's arguments from a parse tree format to - * namespace objects and place those argument object on the object - * stack in preparation for evaluation by the interpreter. - * - ******************************************************************************/ - -acpi_status -acpi_ds_create_operands(struct acpi_walk_state *walk_state, - union acpi_parse_object *first_arg) -{ - acpi_status status = AE_OK; - union acpi_parse_object *arg; - union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS]; - u32 arg_count = 0; - u32 index = walk_state->num_operands; - u32 i; - - ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); - - /* Get all arguments in the list */ - - arg = first_arg; - while (arg) { - if (index >= ACPI_OBJ_NUM_OPERANDS) { - return_ACPI_STATUS(AE_BAD_DATA); - } - - arguments[index] = arg; - walk_state->operands[index] = NULL; - - /* Move on to next argument, if any */ - - arg = arg->common.next; - arg_count++; - index++; - } - - index--; - - /* It is the appropriate order to get objects from the Result stack */ - - for (i = 0; i < arg_count; i++) { - arg = arguments[index]; - - /* Force the filling of the operand stack in inverse order */ - - walk_state->operand_index = (u8) index; - - status = acpi_ds_create_operand(walk_state, arg, index); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - index--; - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Arg #%d (%p) done, Arg1=%p\n", index, arg, - first_arg)); - } - - return_ACPI_STATUS(status); - - cleanup: - /* - * We must undo everything done above; meaning that we must - * pop everything off of the operand stack and delete those - * objects - */ - acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); - - ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index)); - return_ACPI_STATUS(status); -} - -/***************************************************************************** - * - * FUNCTION: acpi_ds_evaluate_name_path - * - * PARAMETERS: walk_state - Current state of the parse tree walk, - * the opcode of current operation should be - * AML_INT_NAMEPATH_OP - * - * RETURN: Status - * - * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent - * interpreter object, convert it to value, if needed, duplicate - * it, if needed, and push it onto the current result stack. - * - ****************************************************************************/ - -acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - union acpi_parse_object *op = walk_state->op; - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *new_obj_desc; - u8 type; - - ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state); - - if (!op->common.parent) { - - /* This happens after certain exception processing */ - - goto exit; - } - - if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || - (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) || - (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) { - - /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */ - - goto exit; - } - - status = acpi_ds_create_operand(walk_state, op, 0); - if (ACPI_FAILURE(status)) { - goto exit; - } - - if (op->common.flags & ACPI_PARSEOP_TARGET) { - new_obj_desc = *operand; - goto push_result; - } - - type = ACPI_GET_OBJECT_TYPE(*operand); - - status = acpi_ex_resolve_to_value(operand, walk_state); - if (ACPI_FAILURE(status)) { - goto exit; - } - - if (type == ACPI_TYPE_INTEGER) { - - /* It was incremented by acpi_ex_resolve_to_value */ - - acpi_ut_remove_reference(*operand); - - status = - acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc, - walk_state); - if (ACPI_FAILURE(status)) { - goto exit; - } - } else { - /* - * The object either was anew created or is - * a Namespace node - don't decrement it. - */ - new_obj_desc = *operand; - } - - /* Cleanup for name-path operand */ - - status = acpi_ds_obj_stack_pop(1, walk_state); - if (ACPI_FAILURE(status)) { - walk_state->result_obj = new_obj_desc; - goto exit; - } - - push_result: - - walk_state->result_obj = new_obj_desc; - - status = acpi_ds_result_push(walk_state->result_obj, walk_state); - if (ACPI_SUCCESS(status)) { - - /* Force to take it from stack */ - - op->common.flags |= ACPI_PARSEOP_IN_STACK; - } - - exit: - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c deleted file mode 100644 index 2482cbd37f25..000000000000 --- a/drivers/acpi/dispatcher/dswexec.c +++ /dev/null @@ -1,746 +0,0 @@ -/****************************************************************************** - * - * Module Name: dswexec - Dispatcher method execution callbacks; - * dispatch to interpreter. - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_DISPATCHER -ACPI_MODULE_NAME("dswexec") - -/* - * Dispatch table for opcode classes - */ -static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch[] = { - acpi_ex_opcode_0A_0T_1R, - acpi_ex_opcode_1A_0T_0R, - acpi_ex_opcode_1A_0T_1R, - acpi_ex_opcode_1A_1T_0R, - acpi_ex_opcode_1A_1T_1R, - acpi_ex_opcode_2A_0T_0R, - acpi_ex_opcode_2A_0T_1R, - acpi_ex_opcode_2A_1T_1R, - acpi_ex_opcode_2A_2T_1R, - acpi_ex_opcode_3A_0T_0R, - acpi_ex_opcode_3A_1T_1R, - acpi_ex_opcode_6A_0T_1R -}; - -/***************************************************************************** - * - * FUNCTION: acpi_ds_get_predicate_value - * - * PARAMETERS: walk_state - Current state of the parse tree walk - * result_obj - if non-zero, pop result from result stack - * - * RETURN: Status - * - * DESCRIPTION: Get the result of a predicate evaluation - * - ****************************************************************************/ - -acpi_status -acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, - union acpi_operand_object *result_obj) -{ - acpi_status status = AE_OK; - union acpi_operand_object *obj_desc; - union acpi_operand_object *local_obj_desc = NULL; - - ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state); - - walk_state->control_state->common.state = 0; - - if (result_obj) { - status = acpi_ds_result_pop(&obj_desc, walk_state); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not get result from predicate evaluation")); - - return_ACPI_STATUS(status); - } - } else { - status = acpi_ds_create_operand(walk_state, walk_state->op, 0); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = - acpi_ex_resolve_to_value(&walk_state->operands[0], - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - obj_desc = walk_state->operands[0]; - } - - if (!obj_desc) { - ACPI_ERROR((AE_INFO, - "No predicate ObjDesc=%p State=%p", - obj_desc, walk_state)); - - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - /* - * Result of predicate evaluation must be an Integer - * object. Implicitly convert the argument if necessary. - */ - status = acpi_ex_convert_to_integer(obj_desc, &local_obj_desc, 16); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, - "Bad predicate (not an integer) ObjDesc=%p State=%p Type=%X", - obj_desc, walk_state, - ACPI_GET_OBJECT_TYPE(obj_desc))); - - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - - /* Truncate the predicate to 32-bits if necessary */ - - acpi_ex_truncate_for32bit_table(local_obj_desc); - - /* - * Save the result of the predicate evaluation on - * the control stack - */ - if (local_obj_desc->integer.value) { - walk_state->control_state->common.value = TRUE; - } else { - /* - * Predicate is FALSE, we will just toss the - * rest of the package - */ - walk_state->control_state->common.value = FALSE; - status = AE_CTRL_FALSE; - } - - /* Predicate can be used for an implicit return value */ - - (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE); - - cleanup: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n", - walk_state->control_state->common.value, - walk_state->op)); - - /* Break to debugger to display result */ - - ACPI_DEBUGGER_EXEC(acpi_db_display_result_object - (local_obj_desc, walk_state)); - - /* - * Delete the predicate result object (we know that - * we don't need it anymore) - */ - if (local_obj_desc != obj_desc) { - acpi_ut_remove_reference(local_obj_desc); - } - acpi_ut_remove_reference(obj_desc); - - walk_state->control_state->common.state = ACPI_CONTROL_NORMAL; - return_ACPI_STATUS(status); -} - -/***************************************************************************** - * - * FUNCTION: acpi_ds_exec_begin_op - * - * PARAMETERS: walk_state - Current state of the parse tree walk - * out_op - Where to return op if a new one is created - * - * RETURN: Status - * - * DESCRIPTION: Descending callback used during the execution of control - * methods. This is where most operators and operands are - * dispatched to the interpreter. - * - ****************************************************************************/ - -acpi_status -acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **out_op) -{ - union acpi_parse_object *op; - acpi_status status = AE_OK; - u32 opcode_class; - - ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state); - - op = walk_state->op; - if (!op) { - status = acpi_ds_load2_begin_op(walk_state, out_op); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - - op = *out_op; - walk_state->op = op; - walk_state->opcode = op->common.aml_opcode; - walk_state->op_info = - acpi_ps_get_opcode_info(op->common.aml_opcode); - - if (acpi_ns_opens_scope(walk_state->op_info->object_type)) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "(%s) Popping scope for Op %p\n", - acpi_ut_get_type_name(walk_state-> - op_info-> - object_type), - op)); - - status = acpi_ds_scope_stack_pop(walk_state); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - } - } - - if (op == walk_state->origin) { - if (out_op) { - *out_op = op; - } - - return_ACPI_STATUS(AE_OK); - } - - /* - * If the previous opcode was a conditional, this opcode - * must be the beginning of the associated predicate. - * Save this knowledge in the current scope descriptor - */ - if ((walk_state->control_state) && - (walk_state->control_state->common.state == - ACPI_CONTROL_CONDITIONAL_EXECUTING)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Exec predicate Op=%p State=%p\n", op, - walk_state)); - - walk_state->control_state->common.state = - ACPI_CONTROL_PREDICATE_EXECUTING; - - /* Save start of predicate */ - - walk_state->control_state->control.predicate_op = op; - } - - opcode_class = walk_state->op_info->class; - - /* We want to send namepaths to the load code */ - - if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { - opcode_class = AML_CLASS_NAMED_OBJECT; - } - - /* - * Handle the opcode based upon the opcode type - */ - switch (opcode_class) { - case AML_CLASS_CONTROL: - - status = acpi_ds_exec_begin_control_op(walk_state, op); - break; - - case AML_CLASS_NAMED_OBJECT: - - if (walk_state->walk_type & ACPI_WALK_METHOD) { - /* - * Found a named object declaration during method execution; - * we must enter this object into the namespace. The created - * object is temporary and will be deleted upon completion of - * the execution of this method. - */ - status = acpi_ds_load2_begin_op(walk_state, NULL); - } - - break; - - case AML_CLASS_EXECUTE: - case AML_CLASS_CREATE: - - break; - - default: - break; - } - - /* Nothing to do here during method execution */ - - return_ACPI_STATUS(status); - - error_exit: - status = acpi_ds_method_error(status, walk_state); - return_ACPI_STATUS(status); -} - -/***************************************************************************** - * - * FUNCTION: acpi_ds_exec_end_op - * - * PARAMETERS: walk_state - Current state of the parse tree walk - * - * RETURN: Status - * - * DESCRIPTION: Ascending callback used during the execution of control - * methods. The only thing we really need to do here is to - * notice the beginning of IF, ELSE, and WHILE blocks. - * - ****************************************************************************/ - -acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) -{ - union acpi_parse_object *op; - acpi_status status = AE_OK; - u32 op_type; - u32 op_class; - union acpi_parse_object *next_op; - union acpi_parse_object *first_arg; - - ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state); - - op = walk_state->op; - op_type = walk_state->op_info->type; - op_class = walk_state->op_info->class; - - if (op_class == AML_CLASS_UNKNOWN) { - ACPI_ERROR((AE_INFO, "Unknown opcode %X", - op->common.aml_opcode)); - return_ACPI_STATUS(AE_NOT_IMPLEMENTED); - } - - first_arg = op->common.value.arg; - - /* Init the walk state */ - - walk_state->num_operands = 0; - walk_state->operand_index = 0; - walk_state->return_desc = NULL; - walk_state->result_obj = NULL; - - /* Call debugger for single step support (DEBUG build only) */ - - ACPI_DEBUGGER_EXEC(status = - acpi_db_single_step(walk_state, op, op_class)); - ACPI_DEBUGGER_EXEC(if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status);} - ) ; - - /* Decode the Opcode Class */ - - switch (op_class) { - case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ - - if (walk_state->opcode == AML_INT_NAMEPATH_OP) { - status = acpi_ds_evaluate_name_path(walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - } - break; - - case AML_CLASS_EXECUTE: /* Most operators with arguments */ - - /* Build resolved operand stack */ - - status = acpi_ds_create_operands(walk_state, first_arg); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* - * All opcodes require operand resolution, with the only exceptions - * being the object_type and size_of operators. - */ - if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) { - - /* Resolve all operands */ - - status = acpi_ex_resolve_operands(walk_state->opcode, - &(walk_state-> - operands - [walk_state-> - num_operands - 1]), - walk_state); - } - - if (ACPI_SUCCESS(status)) { - /* - * Dispatch the request to the appropriate interpreter handler - * routine. There is one routine per opcode "type" based upon the - * number of opcode arguments and return type. - */ - status = - acpi_gbl_op_type_dispatch[op_type] (walk_state); - } else { - /* - * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the - * Local is uninitialized. - */ - if ((status == AE_AML_UNINITIALIZED_LOCAL) && - (walk_state->opcode == AML_STORE_OP) && - (walk_state->operands[0]->common.type == - ACPI_TYPE_LOCAL_REFERENCE) - && (walk_state->operands[1]->common.type == - ACPI_TYPE_LOCAL_REFERENCE) - && (walk_state->operands[0]->reference.class == - walk_state->operands[1]->reference.class) - && (walk_state->operands[0]->reference.value == - walk_state->operands[1]->reference.value)) { - status = AE_OK; - } else { - ACPI_EXCEPTION((AE_INFO, status, - "While resolving operands for [%s]", - acpi_ps_get_opcode_name - (walk_state->opcode))); - } - } - - /* Always delete the argument objects and clear the operand stack */ - - acpi_ds_clear_operands(walk_state); - - /* - * If a result object was returned from above, push it on the - * current result stack - */ - if (ACPI_SUCCESS(status) && walk_state->result_obj) { - status = - acpi_ds_result_push(walk_state->result_obj, - walk_state); - } - break; - - default: - - switch (op_type) { - case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ - - /* 1 Operand, 0 external_result, 0 internal_result */ - - status = acpi_ds_exec_end_control_op(walk_state, op); - - break; - - case AML_TYPE_METHOD_CALL: - - /* - * If the method is referenced from within a package - * declaration, it is not a invocation of the method, just - * a reference to it. - */ - if ((op->asl.parent) && - ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) - || (op->asl.parent->asl.aml_opcode == - AML_VAR_PACKAGE_OP))) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Method Reference in a Package, Op=%p\n", - op)); - - op->common.node = - (struct acpi_namespace_node *)op->asl.value. - arg->asl.node; - acpi_ut_add_reference(op->asl.value.arg->asl. - node->object); - return_ACPI_STATUS(AE_OK); - } - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Method invocation, Op=%p\n", op)); - - /* - * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains - * the method Node pointer - */ - /* next_op points to the op that holds the method name */ - - next_op = first_arg; - - /* next_op points to first argument op */ - - next_op = next_op->common.next; - - /* - * Get the method's arguments and put them on the operand stack - */ - status = acpi_ds_create_operands(walk_state, next_op); - if (ACPI_FAILURE(status)) { - break; - } - - /* - * Since the operands will be passed to another control method, - * we must resolve all local references here (Local variables, - * arguments to *this* method, etc.) - */ - status = acpi_ds_resolve_operands(walk_state); - if (ACPI_FAILURE(status)) { - - /* On error, clear all resolved operands */ - - acpi_ds_clear_operands(walk_state); - break; - } - - /* - * Tell the walk loop to preempt this running method and - * execute the new method - */ - status = AE_CTRL_TRANSFER; - - /* - * Return now; we don't want to disturb anything, - * especially the operand count! - */ - return_ACPI_STATUS(status); - - case AML_TYPE_CREATE_FIELD: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Executing CreateField Buffer/Index Op=%p\n", - op)); - - status = acpi_ds_load2_end_op(walk_state); - if (ACPI_FAILURE(status)) { - break; - } - - status = - acpi_ds_eval_buffer_field_operands(walk_state, op); - break; - - case AML_TYPE_CREATE_OBJECT: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Executing CreateObject (Buffer/Package) Op=%p\n", - op)); - - switch (op->common.parent->common.aml_opcode) { - case AML_NAME_OP: - - /* - * Put the Node on the object stack (Contains the ACPI Name - * of this object) - */ - walk_state->operands[0] = - (void *)op->common.parent->common.node; - walk_state->num_operands = 1; - - status = acpi_ds_create_node(walk_state, - op->common.parent-> - common.node, - op->common.parent); - if (ACPI_FAILURE(status)) { - break; - } - - /* Fall through */ - /*lint -fallthrough */ - - case AML_INT_EVAL_SUBTREE_OP: - - status = - acpi_ds_eval_data_object_operands - (walk_state, op, - acpi_ns_get_attached_object(op->common. - parent->common. - node)); - break; - - default: - - status = - acpi_ds_eval_data_object_operands - (walk_state, op, NULL); - break; - } - - /* - * If a result object was returned from above, push it on the - * current result stack - */ - if (walk_state->result_obj) { - status = - acpi_ds_result_push(walk_state->result_obj, - walk_state); - } - break; - - case AML_TYPE_NAMED_FIELD: - case AML_TYPE_NAMED_COMPLEX: - case AML_TYPE_NAMED_SIMPLE: - case AML_TYPE_NAMED_NO_OBJ: - - status = acpi_ds_load2_end_op(walk_state); - if (ACPI_FAILURE(status)) { - break; - } - - if (op->common.aml_opcode == AML_REGION_OP) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Executing OpRegion Address/Length Op=%p\n", - op)); - - status = - acpi_ds_eval_region_operands(walk_state, - op); - if (ACPI_FAILURE(status)) { - break; - } - } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Executing DataTableRegion Strings Op=%p\n", - op)); - - status = - acpi_ds_eval_table_region_operands - (walk_state, op); - if (ACPI_FAILURE(status)) { - break; - } - } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Executing BankField Op=%p\n", - op)); - - status = - acpi_ds_eval_bank_field_operands(walk_state, - op); - if (ACPI_FAILURE(status)) { - break; - } - } - break; - - case AML_TYPE_UNDEFINED: - - ACPI_ERROR((AE_INFO, - "Undefined opcode type Op=%p", op)); - return_ACPI_STATUS(AE_NOT_IMPLEMENTED); - - case AML_TYPE_BOGUS: - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Internal opcode=%X type Op=%p\n", - walk_state->opcode, op)); - break; - - default: - - ACPI_ERROR((AE_INFO, - "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p", - op_class, op_type, op->common.aml_opcode, - op)); - - status = AE_NOT_IMPLEMENTED; - break; - } - } - - /* - * ACPI 2.0 support for 64-bit integers: Truncate numeric - * result value if we are executing from a 32-bit ACPI table - */ - acpi_ex_truncate_for32bit_table(walk_state->result_obj); - - /* - * Check if we just completed the evaluation of a - * conditional predicate - */ - if ((ACPI_SUCCESS(status)) && - (walk_state->control_state) && - (walk_state->control_state->common.state == - ACPI_CONTROL_PREDICATE_EXECUTING) && - (walk_state->control_state->control.predicate_op == op)) { - status = - acpi_ds_get_predicate_value(walk_state, - walk_state->result_obj); - walk_state->result_obj = NULL; - } - - cleanup: - - if (walk_state->result_obj) { - - /* Break to debugger to display result */ - - ACPI_DEBUGGER_EXEC(acpi_db_display_result_object - (walk_state->result_obj, walk_state)); - - /* - * Delete the result op if and only if: - * Parent will not use the result -- such as any - * non-nested type2 op in a method (parent will be method) - */ - acpi_ds_delete_result_if_not_used(op, walk_state->result_obj, - walk_state); - } -#ifdef _UNDER_DEVELOPMENT - - if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) { - acpi_db_method_end(walk_state); - } -#endif - - /* Invoke exception handler on error */ - - if (ACPI_FAILURE(status)) { - status = acpi_ds_method_error(status, walk_state); - } - - /* Always clear the object stack */ - - walk_state->num_operands = 0; - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c deleted file mode 100644 index 2d71ceda3d56..000000000000 --- a/drivers/acpi/dispatcher/dswload.c +++ /dev/null @@ -1,1203 +0,0 @@ -/****************************************************************************** - * - * Module Name: dswload - Dispatcher namespace load callbacks - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef ACPI_ASL_COMPILER -#include -#endif - -#define _COMPONENT ACPI_DISPATCHER -ACPI_MODULE_NAME("dswload") - -/******************************************************************************* - * - * FUNCTION: acpi_ds_init_callbacks - * - * PARAMETERS: walk_state - Current state of the parse tree walk - * pass_number - 1, 2, or 3 - * - * RETURN: Status - * - * DESCRIPTION: Init walk state callbacks - * - ******************************************************************************/ -acpi_status -acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) -{ - - switch (pass_number) { - case 1: - walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | - ACPI_PARSE_DELETE_TREE; - walk_state->descending_callback = acpi_ds_load1_begin_op; - walk_state->ascending_callback = acpi_ds_load1_end_op; - break; - - case 2: - walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | - ACPI_PARSE_DELETE_TREE; - walk_state->descending_callback = acpi_ds_load2_begin_op; - walk_state->ascending_callback = acpi_ds_load2_end_op; - break; - - case 3: -#ifndef ACPI_NO_METHOD_EXECUTION - walk_state->parse_flags |= ACPI_PARSE_EXECUTE | - ACPI_PARSE_DELETE_TREE; - walk_state->descending_callback = acpi_ds_exec_begin_op; - walk_state->ascending_callback = acpi_ds_exec_end_op; -#endif - break; - - default: - return (AE_BAD_PARAMETER); - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_load1_begin_op - * - * PARAMETERS: walk_state - Current state of the parse tree walk - * out_op - Where to return op if a new one is created - * - * RETURN: Status - * - * DESCRIPTION: Descending callback used during the loading of ACPI tables. - * - ******************************************************************************/ - -acpi_status -acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, - union acpi_parse_object ** out_op) -{ - union acpi_parse_object *op; - struct acpi_namespace_node *node; - acpi_status status; - acpi_object_type object_type; - char *path; - u32 flags; - - ACPI_FUNCTION_TRACE(ds_load1_begin_op); - - op = walk_state->op; - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, - walk_state)); - - /* We are only interested in opcodes that have an associated name */ - - if (op) { - if (!(walk_state->op_info->flags & AML_NAMED)) { - *out_op = op; - return_ACPI_STATUS(AE_OK); - } - - /* Check if this object has already been installed in the namespace */ - - if (op->common.node) { - *out_op = op; - return_ACPI_STATUS(AE_OK); - } - } - - path = acpi_ps_get_next_namestring(&walk_state->parser_state); - - /* Map the raw opcode into an internal object type */ - - object_type = walk_state->op_info->object_type; - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "State=%p Op=%p [%s]\n", walk_state, op, - acpi_ut_get_type_name(object_type))); - - switch (walk_state->opcode) { - case AML_SCOPE_OP: - - /* - * The target name of the Scope() operator must exist at this point so - * that we can actually open the scope to enter new names underneath it. - * Allow search-to-root for single namesegs. - */ - status = - acpi_ns_lookup(walk_state->scope_info, path, object_type, - ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, - walk_state, &(node)); -#ifdef ACPI_ASL_COMPILER - if (status == AE_NOT_FOUND) { - /* - * Table disassembly: - * Target of Scope() not found. Generate an External for it, and - * insert the name into the namespace. - */ - acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0); - status = - acpi_ns_lookup(walk_state->scope_info, path, - object_type, ACPI_IMODE_LOAD_PASS1, - ACPI_NS_SEARCH_PARENT, walk_state, - &node); - } -#endif - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(path, status); - return_ACPI_STATUS(status); - } - - /* - * Check to make sure that the target is - * one of the opcodes that actually opens a scope - */ - switch (node->type) { - case ACPI_TYPE_ANY: - case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_POWER: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_THERMAL: - - /* These are acceptable types */ - break; - - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - - /* - * These types we will allow, but we will change the type. This - * enables some existing code of the form: - * - * Name (DEB, 0) - * Scope (DEB) { ... } - * - * Note: silently change the type here. On the second pass, we will report - * a warning - */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", - path, - acpi_ut_get_type_name(node->type))); - - node->type = ACPI_TYPE_ANY; - walk_state->scope_info->common.value = ACPI_TYPE_ANY; - break; - - default: - - /* All other types are an error */ - - ACPI_ERROR((AE_INFO, - "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)", - acpi_ut_get_type_name(node->type), path)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - break; - - default: - /* - * For all other named opcodes, we will enter the name into - * the namespace. - * - * Setup the search flags. - * Since we are entering a name into the namespace, we do not want to - * enable the search-to-root upsearch. - * - * There are only two conditions where it is acceptable that the name - * already exists: - * 1) the Scope() operator can reopen a scoping object that was - * previously defined (Scope, Method, Device, etc.) - * 2) Whenever we are parsing a deferred opcode (op_region, Buffer, - * buffer_field, or Package), the name of the object is already - * in the namespace. - */ - if (walk_state->deferred_node) { - - /* This name is already in the namespace, get the node */ - - node = walk_state->deferred_node; - status = AE_OK; - break; - } - - /* - * If we are executing a method, do not create any namespace objects - * during the load phase, only during execution. - */ - if (walk_state->method_node) { - node = NULL; - status = AE_OK; - break; - } - - flags = ACPI_NS_NO_UPSEARCH; - if ((walk_state->opcode != AML_SCOPE_OP) && - (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) { - flags |= ACPI_NS_ERROR_IF_FOUND; - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "[%s] Cannot already exist\n", - acpi_ut_get_type_name(object_type))); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "[%s] Both Find or Create allowed\n", - acpi_ut_get_type_name(object_type))); - } - - /* - * Enter the named type into the internal namespace. We enter the name - * as we go downward in the parse tree. Any necessary subobjects that - * involve arguments to the opcode must be created as we go back up the - * parse tree later. - */ - status = - acpi_ns_lookup(walk_state->scope_info, path, object_type, - ACPI_IMODE_LOAD_PASS1, flags, walk_state, - &node); - if (ACPI_FAILURE(status)) { - if (status == AE_ALREADY_EXISTS) { - - /* The name already exists in this scope */ - - if (node->flags & ANOBJ_IS_EXTERNAL) { - /* - * Allow one create on an object or segment that was - * previously declared External - */ - node->flags &= ~ANOBJ_IS_EXTERNAL; - node->type = (u8) object_type; - - /* Just retyped a node, probably will need to open a scope */ - - if (acpi_ns_opens_scope(object_type)) { - status = - acpi_ds_scope_stack_push - (node, object_type, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS - (status); - } - } - - status = AE_OK; - } - } - - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(path, status); - return_ACPI_STATUS(status); - } - } - break; - } - - /* Common exit */ - - if (!op) { - - /* Create a new op */ - - op = acpi_ps_alloc_op(walk_state->opcode); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - } - - /* Initialize the op */ - -#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) - op->named.path = ACPI_CAST_PTR(u8, path); -#endif - - if (node) { - /* - * Put the Node in the "op" object that the parser uses, so we - * can get it again quickly when this scope is closed - */ - op->common.node = node; - op->named.name = node->name.integer; - } - - acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state), - op); - *out_op = op; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_load1_end_op - * - * PARAMETERS: walk_state - Current state of the parse tree walk - * - * RETURN: Status - * - * DESCRIPTION: Ascending callback used during the loading of the namespace, - * both control methods and everything else. - * - ******************************************************************************/ - -acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) -{ - union acpi_parse_object *op; - acpi_object_type object_type; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ds_load1_end_op); - - op = walk_state->op; - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, - walk_state)); - - /* We are only interested in opcodes that have an associated name */ - - if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the object type to determine if we should pop the scope */ - - object_type = walk_state->op_info->object_type; - -#ifndef ACPI_NO_METHOD_EXECUTION - if (walk_state->op_info->flags & AML_FIELD) { - /* - * If we are executing a method, do not create any namespace objects - * during the load phase, only during execution. - */ - if (!walk_state->method_node) { - if (walk_state->opcode == AML_FIELD_OP || - walk_state->opcode == AML_BANK_FIELD_OP || - walk_state->opcode == AML_INDEX_FIELD_OP) { - status = - acpi_ds_init_field_objects(op, walk_state); - } - } - return_ACPI_STATUS(status); - } - - /* - * If we are executing a method, do not create any namespace objects - * during the load phase, only during execution. - */ - if (!walk_state->method_node) { - if (op->common.aml_opcode == AML_REGION_OP) { - status = - acpi_ex_create_region(op->named.data, - op->named.length, - (acpi_adr_space_type) ((op-> - common. - value. - arg)-> - common. - value. - integer), - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { - status = - acpi_ex_create_region(op->named.data, - op->named.length, - REGION_DATA_TABLE, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - } -#endif - - if (op->common.aml_opcode == AML_NAME_OP) { - - /* For Name opcode, get the object type from the argument */ - - if (op->common.value.arg) { - object_type = (acpi_ps_get_opcode_info((op->common. - value.arg)-> - common. - aml_opcode))-> - object_type; - - /* Set node type if we have a namespace node */ - - if (op->common.node) { - op->common.node->type = (u8) object_type; - } - } - } - - /* - * If we are executing a method, do not create any namespace objects - * during the load phase, only during execution. - */ - if (!walk_state->method_node) { - if (op->common.aml_opcode == AML_METHOD_OP) { - /* - * method_op pkg_length name_string method_flags term_list - * - * Note: We must create the method node/object pair as soon as we - * see the method declaration. This allows later pass1 parsing - * of invocations of the method (need to know the number of - * arguments.) - */ - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "LOADING-Method: State=%p Op=%p NamedObj=%p\n", - walk_state, op, op->named.node)); - - if (!acpi_ns_get_attached_object(op->named.node)) { - walk_state->operands[0] = - ACPI_CAST_PTR(void, op->named.node); - walk_state->num_operands = 1; - - status = - acpi_ds_create_operands(walk_state, - op->common.value. - arg); - if (ACPI_SUCCESS(status)) { - status = - acpi_ex_create_method(op->named. - data, - op->named. - length, - walk_state); - } - - walk_state->operands[0] = NULL; - walk_state->num_operands = 0; - - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - } - } - - /* Pop the scope stack (only if loading a table) */ - - if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "(%s): Popping scope for Op %p\n", - acpi_ut_get_type_name(object_type), op)); - - status = acpi_ds_scope_stack_pop(walk_state); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_load2_begin_op - * - * PARAMETERS: walk_state - Current state of the parse tree walk - * out_op - Wher to return op if a new one is created - * - * RETURN: Status - * - * DESCRIPTION: Descending callback used during the loading of ACPI tables. - * - ******************************************************************************/ - -acpi_status -acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **out_op) -{ - union acpi_parse_object *op; - struct acpi_namespace_node *node; - acpi_status status; - acpi_object_type object_type; - char *buffer_ptr; - u32 flags; - - ACPI_FUNCTION_TRACE(ds_load2_begin_op); - - op = walk_state->op; - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, - walk_state)); - - if (op) { - if ((walk_state->control_state) && - (walk_state->control_state->common.state == - ACPI_CONTROL_CONDITIONAL_EXECUTING)) { - - /* We are executing a while loop outside of a method */ - - status = acpi_ds_exec_begin_op(walk_state, out_op); - return_ACPI_STATUS(status); - } - - /* We only care about Namespace opcodes here */ - - if ((!(walk_state->op_info->flags & AML_NSOPCODE) && - (walk_state->opcode != AML_INT_NAMEPATH_OP)) || - (!(walk_state->op_info->flags & AML_NAMED))) { -#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE - if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || - (walk_state->op_info->class == AML_CLASS_CONTROL)) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Begin/EXEC: %s (fl %8.8X)\n", - walk_state->op_info->name, - walk_state->op_info->flags)); - - /* Executing a type1 or type2 opcode outside of a method */ - - status = - acpi_ds_exec_begin_op(walk_state, out_op); - return_ACPI_STATUS(status); - } -#endif - return_ACPI_STATUS(AE_OK); - } - - /* Get the name we are going to enter or lookup in the namespace */ - - if (walk_state->opcode == AML_INT_NAMEPATH_OP) { - - /* For Namepath op, get the path string */ - - buffer_ptr = op->common.value.string; - if (!buffer_ptr) { - - /* No name, just exit */ - - return_ACPI_STATUS(AE_OK); - } - } else { - /* Get name from the op */ - - buffer_ptr = ACPI_CAST_PTR(char, &op->named.name); - } - } else { - /* Get the namestring from the raw AML */ - - buffer_ptr = - acpi_ps_get_next_namestring(&walk_state->parser_state); - } - - /* Map the opcode into an internal object type */ - - object_type = walk_state->op_info->object_type; - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "State=%p Op=%p Type=%X\n", walk_state, op, - object_type)); - - switch (walk_state->opcode) { - case AML_FIELD_OP: - case AML_BANK_FIELD_OP: - case AML_INDEX_FIELD_OP: - - node = NULL; - status = AE_OK; - break; - - case AML_INT_NAMEPATH_OP: - /* - * The name_path is an object reference to an existing object. - * Don't enter the name into the namespace, but look it up - * for use later. - */ - status = - acpi_ns_lookup(walk_state->scope_info, buffer_ptr, - object_type, ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT, walk_state, &(node)); - break; - - case AML_SCOPE_OP: - /* - * The Path is an object reference to an existing object. - * Don't enter the name into the namespace, but look it up - * for use later. - */ - status = - acpi_ns_lookup(walk_state->scope_info, buffer_ptr, - object_type, ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT, walk_state, &(node)); - if (ACPI_FAILURE(status)) { -#ifdef ACPI_ASL_COMPILER - if (status == AE_NOT_FOUND) { - status = AE_OK; - } else { - ACPI_ERROR_NAMESPACE(buffer_ptr, status); - } -#else - ACPI_ERROR_NAMESPACE(buffer_ptr, status); -#endif - return_ACPI_STATUS(status); - } - - /* - * We must check to make sure that the target is - * one of the opcodes that actually opens a scope - */ - switch (node->type) { - case ACPI_TYPE_ANY: - case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_POWER: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_THERMAL: - - /* These are acceptable types */ - break; - - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - - /* - * These types we will allow, but we will change the type. This - * enables some existing code of the form: - * - * Name (DEB, 0) - * Scope (DEB) { ... } - */ - ACPI_WARNING((AE_INFO, - "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)", - buffer_ptr, - acpi_ut_get_type_name(node->type))); - - node->type = ACPI_TYPE_ANY; - walk_state->scope_info->common.value = ACPI_TYPE_ANY; - break; - - default: - - /* All other types are an error */ - - ACPI_ERROR((AE_INFO, - "Invalid type (%s) for target of Scope operator [%4.4s]", - acpi_ut_get_type_name(node->type), - buffer_ptr)); - - return (AE_AML_OPERAND_TYPE); - } - break; - - default: - - /* All other opcodes */ - - if (op && op->common.node) { - - /* This op/node was previously entered into the namespace */ - - node = op->common.node; - - if (acpi_ns_opens_scope(object_type)) { - status = - acpi_ds_scope_stack_push(node, object_type, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - return_ACPI_STATUS(AE_OK); - } - - /* - * Enter the named type into the internal namespace. We enter the name - * as we go downward in the parse tree. Any necessary subobjects that - * involve arguments to the opcode must be created as we go back up the - * parse tree later. - * - * Note: Name may already exist if we are executing a deferred opcode. - */ - if (walk_state->deferred_node) { - - /* This name is already in the namespace, get the node */ - - node = walk_state->deferred_node; - status = AE_OK; - break; - } - - flags = ACPI_NS_NO_UPSEARCH; - if (walk_state->pass_number == ACPI_IMODE_EXECUTE) { - - /* Execution mode, node cannot already exist, node is temporary */ - - flags |= (ACPI_NS_ERROR_IF_FOUND | ACPI_NS_TEMPORARY); - } - - /* Add new entry or lookup existing entry */ - - status = - acpi_ns_lookup(walk_state->scope_info, buffer_ptr, - object_type, ACPI_IMODE_LOAD_PASS2, flags, - walk_state, &node); - - if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "***New Node [%4.4s] %p is temporary\n", - acpi_ut_get_node_name(node), node)); - } - break; - } - - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(buffer_ptr, status); - return_ACPI_STATUS(status); - } - - if (!op) { - - /* Create a new op */ - - op = acpi_ps_alloc_op(walk_state->opcode); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Initialize the new op */ - - if (node) { - op->named.name = node->name.integer; - } - *out_op = op; - } - - /* - * Put the Node in the "op" object that the parser uses, so we - * can get it again quickly when this scope is closed - */ - op->common.node = node; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_load2_end_op - * - * PARAMETERS: walk_state - Current state of the parse tree walk - * - * RETURN: Status - * - * DESCRIPTION: Ascending callback used during the loading of the namespace, - * both control methods and everything else. - * - ******************************************************************************/ - -acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) -{ - union acpi_parse_object *op; - acpi_status status = AE_OK; - acpi_object_type object_type; - struct acpi_namespace_node *node; - union acpi_parse_object *arg; - struct acpi_namespace_node *new_node; -#ifndef ACPI_NO_METHOD_EXECUTION - u32 i; - u8 region_space; -#endif - - ACPI_FUNCTION_TRACE(ds_load2_end_op); - - op = walk_state->op; - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", - walk_state->op_info->name, op, walk_state)); - - /* Check if opcode had an associated namespace object */ - - if (!(walk_state->op_info->flags & AML_NSOBJECT)) { -#ifndef ACPI_NO_METHOD_EXECUTION -#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE - /* No namespace object. Executable opcode? */ - - if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || - (walk_state->op_info->class == AML_CLASS_CONTROL)) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "End/EXEC: %s (fl %8.8X)\n", - walk_state->op_info->name, - walk_state->op_info->flags)); - - /* Executing a type1 or type2 opcode outside of a method */ - - status = acpi_ds_exec_end_op(walk_state); - return_ACPI_STATUS(status); - } -#endif -#endif - return_ACPI_STATUS(AE_OK); - } - - if (op->common.aml_opcode == AML_SCOPE_OP) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Ending scope Op=%p State=%p\n", op, - walk_state)); - } - - object_type = walk_state->op_info->object_type; - - /* - * Get the Node/name from the earlier lookup - * (It was saved in the *op structure) - */ - node = op->common.node; - - /* - * Put the Node on the object stack (Contains the ACPI Name of - * this object) - */ - walk_state->operands[0] = (void *)node; - walk_state->num_operands = 1; - - /* Pop the scope stack */ - - if (acpi_ns_opens_scope(object_type) && - (op->common.aml_opcode != AML_INT_METHODCALL_OP)) { - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "(%s) Popping scope for Op %p\n", - acpi_ut_get_type_name(object_type), op)); - - status = acpi_ds_scope_stack_pop(walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - } - - /* - * Named operations are as follows: - * - * AML_ALIAS - * AML_BANKFIELD - * AML_CREATEBITFIELD - * AML_CREATEBYTEFIELD - * AML_CREATEDWORDFIELD - * AML_CREATEFIELD - * AML_CREATEQWORDFIELD - * AML_CREATEWORDFIELD - * AML_DATA_REGION - * AML_DEVICE - * AML_EVENT - * AML_FIELD - * AML_INDEXFIELD - * AML_METHOD - * AML_METHODCALL - * AML_MUTEX - * AML_NAME - * AML_NAMEDFIELD - * AML_OPREGION - * AML_POWERRES - * AML_PROCESSOR - * AML_SCOPE - * AML_THERMALZONE - */ - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", - acpi_ps_get_opcode_name(op->common.aml_opcode), - walk_state, op, node)); - - /* Decode the opcode */ - - arg = op->common.value.arg; - - switch (walk_state->op_info->type) { -#ifndef ACPI_NO_METHOD_EXECUTION - - case AML_TYPE_CREATE_FIELD: - /* - * Create the field object, but the field buffer and index must - * be evaluated later during the execution phase - */ - status = acpi_ds_create_buffer_field(op, walk_state); - break; - - case AML_TYPE_NAMED_FIELD: - /* - * If we are executing a method, initialize the field - */ - if (walk_state->method_node) { - status = acpi_ds_init_field_objects(op, walk_state); - } - - switch (op->common.aml_opcode) { - case AML_INDEX_FIELD_OP: - - status = - acpi_ds_create_index_field(op, - (acpi_handle) arg-> - common.node, walk_state); - break; - - case AML_BANK_FIELD_OP: - - status = - acpi_ds_create_bank_field(op, arg->common.node, - walk_state); - break; - - case AML_FIELD_OP: - - status = - acpi_ds_create_field(op, arg->common.node, - walk_state); - break; - - default: - /* All NAMED_FIELD opcodes must be handled above */ - break; - } - break; - - case AML_TYPE_NAMED_SIMPLE: - - status = acpi_ds_create_operands(walk_state, arg); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - switch (op->common.aml_opcode) { - case AML_PROCESSOR_OP: - - status = acpi_ex_create_processor(walk_state); - break; - - case AML_POWER_RES_OP: - - status = acpi_ex_create_power_resource(walk_state); - break; - - case AML_MUTEX_OP: - - status = acpi_ex_create_mutex(walk_state); - break; - - case AML_EVENT_OP: - - status = acpi_ex_create_event(walk_state); - break; - - case AML_ALIAS_OP: - - status = acpi_ex_create_alias(walk_state); - break; - - default: - /* Unknown opcode */ - - status = AE_OK; - goto cleanup; - } - - /* Delete operands */ - - for (i = 1; i < walk_state->num_operands; i++) { - acpi_ut_remove_reference(walk_state->operands[i]); - walk_state->operands[i] = NULL; - } - - break; -#endif /* ACPI_NO_METHOD_EXECUTION */ - - case AML_TYPE_NAMED_COMPLEX: - - switch (op->common.aml_opcode) { -#ifndef ACPI_NO_METHOD_EXECUTION - case AML_REGION_OP: - case AML_DATA_REGION_OP: - - if (op->common.aml_opcode == AML_REGION_OP) { - region_space = (acpi_adr_space_type) - ((op->common.value.arg)->common.value. - integer); - } else { - region_space = REGION_DATA_TABLE; - } - - /* - * If we are executing a method, initialize the region - */ - if (walk_state->method_node) { - status = - acpi_ex_create_region(op->named.data, - op->named.length, - region_space, - walk_state); - if (ACPI_FAILURE(status)) { - return (status); - } - } - - /* - * The op_region is not fully parsed at this time. Only valid - * argument is the space_id. (We must save the address of the - * AML of the address and length operands) - */ - - /* - * If we have a valid region, initialize it - * Namespace is NOT locked at this point. - */ - status = - acpi_ev_initialize_region - (acpi_ns_get_attached_object(node), FALSE); - if (ACPI_FAILURE(status)) { - /* - * If AE_NOT_EXIST is returned, it is not fatal - * because many regions get created before a handler - * is installed for said region. - */ - if (AE_NOT_EXIST == status) { - status = AE_OK; - } - } - break; - - case AML_NAME_OP: - - status = acpi_ds_create_node(walk_state, node, op); - break; - - case AML_METHOD_OP: - /* - * method_op pkg_length name_string method_flags term_list - * - * Note: We must create the method node/object pair as soon as we - * see the method declaration. This allows later pass1 parsing - * of invocations of the method (need to know the number of - * arguments.) - */ - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "LOADING-Method: State=%p Op=%p NamedObj=%p\n", - walk_state, op, op->named.node)); - - if (!acpi_ns_get_attached_object(op->named.node)) { - walk_state->operands[0] = - ACPI_CAST_PTR(void, op->named.node); - walk_state->num_operands = 1; - - status = - acpi_ds_create_operands(walk_state, - op->common.value. - arg); - if (ACPI_SUCCESS(status)) { - status = - acpi_ex_create_method(op->named. - data, - op->named. - length, - walk_state); - } - walk_state->operands[0] = NULL; - walk_state->num_operands = 0; - - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - break; - -#endif /* ACPI_NO_METHOD_EXECUTION */ - - default: - /* All NAMED_COMPLEX opcodes must be handled above */ - break; - } - break; - - case AML_CLASS_INTERNAL: - - /* case AML_INT_NAMEPATH_OP: */ - break; - - case AML_CLASS_METHOD_CALL: - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", - walk_state, op, node)); - - /* - * Lookup the method name and save the Node - */ - status = - acpi_ns_lookup(walk_state->scope_info, - arg->common.value.string, ACPI_TYPE_ANY, - ACPI_IMODE_LOAD_PASS2, - ACPI_NS_SEARCH_PARENT | - ACPI_NS_DONT_OPEN_SCOPE, walk_state, - &(new_node)); - if (ACPI_SUCCESS(status)) { - /* - * Make sure that what we found is indeed a method - * We didn't search for a method on purpose, to see if the name - * would resolve - */ - if (new_node->type != ACPI_TYPE_METHOD) { - status = AE_AML_OPERAND_TYPE; - } - - /* We could put the returned object (Node) on the object stack for - * later, but for now, we will put it in the "op" object that the - * parser uses, so we can get it again at the end of this scope - */ - op->common.node = new_node; - } else { - ACPI_ERROR_NAMESPACE(arg->common.value.string, status); - } - break; - - default: - break; - } - - cleanup: - - /* Remove the Node pushed at the very beginning */ - - walk_state->operands[0] = NULL; - walk_state->num_operands = 0; - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c deleted file mode 100644 index 8030541a49f7..000000000000 --- a/drivers/acpi/dispatcher/dswscope.c +++ /dev/null @@ -1,214 +0,0 @@ -/****************************************************************************** - * - * Module Name: dswscope - Scope stack manipulation - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_DISPATCHER -ACPI_MODULE_NAME("dswscope") - -/**************************************************************************** - * - * FUNCTION: acpi_ds_scope_stack_clear - * - * PARAMETERS: walk_state - Current state - * - * RETURN: None - * - * DESCRIPTION: Pop (and free) everything on the scope stack except the - * root scope object (which remains at the stack top.) - * - ***************************************************************************/ -void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state) -{ - union acpi_generic_state *scope_info; - - ACPI_FUNCTION_NAME(ds_scope_stack_clear); - - while (walk_state->scope_info) { - - /* Pop a scope off the stack */ - - scope_info = walk_state->scope_info; - walk_state->scope_info = scope_info->scope.next; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Popped object type (%s)\n", - acpi_ut_get_type_name(scope_info->common. - value))); - acpi_ut_delete_generic_state(scope_info); - } -} - -/**************************************************************************** - * - * FUNCTION: acpi_ds_scope_stack_push - * - * PARAMETERS: Node - Name to be made current - * Type - Type of frame being pushed - * walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Push the current scope on the scope stack, and make the - * passed Node current. - * - ***************************************************************************/ - -acpi_status -acpi_ds_scope_stack_push(struct acpi_namespace_node *node, - acpi_object_type type, - struct acpi_walk_state *walk_state) -{ - union acpi_generic_state *scope_info; - union acpi_generic_state *old_scope_info; - - ACPI_FUNCTION_TRACE(ds_scope_stack_push); - - if (!node) { - - /* Invalid scope */ - - ACPI_ERROR((AE_INFO, "Null scope parameter")); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Make sure object type is valid */ - - if (!acpi_ut_valid_object_type(type)) { - ACPI_WARNING((AE_INFO, "Invalid object type: 0x%X", type)); - } - - /* Allocate a new scope object */ - - scope_info = acpi_ut_create_generic_state(); - if (!scope_info) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Init new scope object */ - - scope_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_WSCOPE; - scope_info->scope.node = node; - scope_info->common.value = (u16) type; - - walk_state->scope_depth++; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[%.2d] Pushed scope ", - (u32) walk_state->scope_depth)); - - old_scope_info = walk_state->scope_info; - if (old_scope_info) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, - "[%4.4s] (%s)", - acpi_ut_get_node_name(old_scope_info-> - scope.node), - acpi_ut_get_type_name(old_scope_info-> - common.value))); - } else { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (%s)", "ROOT")); - } - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, - ", New scope -> [%4.4s] (%s)\n", - acpi_ut_get_node_name(scope_info->scope.node), - acpi_ut_get_type_name(scope_info->common.value))); - - /* Push new scope object onto stack */ - - acpi_ut_push_generic_state(&walk_state->scope_info, scope_info); - return_ACPI_STATUS(AE_OK); -} - -/**************************************************************************** - * - * FUNCTION: acpi_ds_scope_stack_pop - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Pop the scope stack once. - * - ***************************************************************************/ - -acpi_status acpi_ds_scope_stack_pop(struct acpi_walk_state *walk_state) -{ - union acpi_generic_state *scope_info; - union acpi_generic_state *new_scope_info; - - ACPI_FUNCTION_TRACE(ds_scope_stack_pop); - - /* - * Pop scope info object off the stack. - */ - scope_info = acpi_ut_pop_generic_state(&walk_state->scope_info); - if (!scope_info) { - return_ACPI_STATUS(AE_STACK_UNDERFLOW); - } - - walk_state->scope_depth--; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[%.2d] Popped scope [%4.4s] (%s), New scope -> ", - (u32) walk_state->scope_depth, - acpi_ut_get_node_name(scope_info->scope.node), - acpi_ut_get_type_name(scope_info->common.value))); - - new_scope_info = walk_state->scope_info; - if (new_scope_info) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, - "[%4.4s] (%s)\n", - acpi_ut_get_node_name(new_scope_info-> - scope.node), - acpi_ut_get_type_name(new_scope_info-> - common.value))); - } else { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (ROOT)\n")); - } - - acpi_ut_delete_generic_state(scope_info); - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c deleted file mode 100644 index a7543c43c151..000000000000 --- a/drivers/acpi/dispatcher/dswstate.c +++ /dev/null @@ -1,753 +0,0 @@ -/****************************************************************************** - * - * Module Name: dswstate - Dispatcher parse tree walk management routines - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_DISPATCHER -ACPI_MODULE_NAME("dswstate") - - /* Local prototypes */ -static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws); -static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws); - -/******************************************************************************* - * - * FUNCTION: acpi_ds_result_pop - * - * PARAMETERS: Object - Where to return the popped object - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Pop an object off the top of this walk's result stack - * - ******************************************************************************/ - -acpi_status -acpi_ds_result_pop(union acpi_operand_object **object, - struct acpi_walk_state *walk_state) -{ - u32 index; - union acpi_generic_state *state; - acpi_status status; - - ACPI_FUNCTION_NAME(ds_result_pop); - - state = walk_state->results; - - /* Incorrect state of result stack */ - - if (state && !walk_state->result_count) { - ACPI_ERROR((AE_INFO, "No results on result stack")); - return (AE_AML_INTERNAL); - } - - if (!state && walk_state->result_count) { - ACPI_ERROR((AE_INFO, "No result state for result stack")); - return (AE_AML_INTERNAL); - } - - /* Empty result stack */ - - if (!state) { - ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", - walk_state)); - return (AE_AML_NO_RETURN_VALUE); - } - - /* Return object of the top element and clean that top element result stack */ - - walk_state->result_count--; - index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; - - *object = state->results.obj_desc[index]; - if (!*object) { - ACPI_ERROR((AE_INFO, - "No result objects on result stack, State=%p", - walk_state)); - return (AE_AML_NO_RETURN_VALUE); - } - - state->results.obj_desc[index] = NULL; - if (index == 0) { - status = acpi_ds_result_stack_pop(walk_state); - if (ACPI_FAILURE(status)) { - return (status); - } - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, - acpi_ut_get_object_type_name(*object), - index, walk_state, walk_state->result_count)); - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_result_push - * - * PARAMETERS: Object - Where to return the popped object - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Push an object onto the current result stack - * - ******************************************************************************/ - -acpi_status -acpi_ds_result_push(union acpi_operand_object * object, - struct acpi_walk_state * walk_state) -{ - union acpi_generic_state *state; - acpi_status status; - u32 index; - - ACPI_FUNCTION_NAME(ds_result_push); - - if (walk_state->result_count > walk_state->result_size) { - ACPI_ERROR((AE_INFO, "Result stack is full")); - return (AE_AML_INTERNAL); - } else if (walk_state->result_count == walk_state->result_size) { - - /* Extend the result stack */ - - status = acpi_ds_result_stack_push(walk_state); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Failed to extend the result stack")); - return (status); - } - } - - if (!(walk_state->result_count < walk_state->result_size)) { - ACPI_ERROR((AE_INFO, "No free elements in result stack")); - return (AE_AML_INTERNAL); - } - - state = walk_state->results; - if (!state) { - ACPI_ERROR((AE_INFO, "No result stack frame during push")); - return (AE_AML_INTERNAL); - } - - if (!object) { - ACPI_ERROR((AE_INFO, - "Null Object! Obj=%p State=%p Num=%X", - object, walk_state, walk_state->result_count)); - return (AE_BAD_PARAMETER); - } - - /* Assign the address of object to the top free element of result stack */ - - index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; - state->results.obj_desc[index] = object; - walk_state->result_count++; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", - object, - acpi_ut_get_object_type_name((union - acpi_operand_object *) - object), walk_state, - walk_state->result_count, - walk_state->current_result)); - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_result_stack_push - * - * PARAMETERS: walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Push an object onto the walk_state result stack - * - ******************************************************************************/ - -static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_NAME(ds_result_stack_push); - - /* Check for stack overflow */ - - if (((u32) walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) > - ACPI_RESULTS_OBJ_NUM_MAX) { - ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%X", - walk_state, walk_state->result_size)); - return (AE_STACK_OVERFLOW); - } - - state = acpi_ut_create_generic_state(); - if (!state) { - return (AE_NO_MEMORY); - } - - state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT; - acpi_ut_push_generic_state(&walk_state->results, state); - - /* Increase the length of the result stack by the length of frame */ - - walk_state->result_size += ACPI_RESULTS_FRAME_OBJ_NUM; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n", - state, walk_state)); - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_result_stack_pop - * - * PARAMETERS: walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Pop an object off of the walk_state result stack - * - ******************************************************************************/ - -static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_NAME(ds_result_stack_pop); - - /* Check for stack underflow */ - - if (walk_state->results == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Result stack underflow - State=%p\n", - walk_state)); - return (AE_AML_NO_OPERAND); - } - - if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) { - ACPI_ERROR((AE_INFO, "Insufficient result stack size")); - return (AE_AML_INTERNAL); - } - - state = acpi_ut_pop_generic_state(&walk_state->results); - acpi_ut_delete_generic_state(state); - - /* Decrease the length of result stack by the length of frame */ - - walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Result=%p RemainingResults=%X State=%p\n", - state, walk_state->result_count, walk_state)); - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_obj_stack_push - * - * PARAMETERS: Object - Object to push - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Push an object onto this walk's object/operand stack - * - ******************************************************************************/ - -acpi_status -acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) -{ - ACPI_FUNCTION_NAME(ds_obj_stack_push); - - /* Check for stack overflow */ - - if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) { - ACPI_ERROR((AE_INFO, - "Object stack overflow! Obj=%p State=%p #Ops=%X", - object, walk_state, walk_state->num_operands)); - return (AE_STACK_OVERFLOW); - } - - /* Put the object onto the stack */ - - walk_state->operands[walk_state->operand_index] = object; - walk_state->num_operands++; - - /* For the usual order of filling the operand stack */ - - walk_state->operand_index++; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", - object, - acpi_ut_get_object_type_name((union - acpi_operand_object *) - object), walk_state, - walk_state->num_operands)); - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_obj_stack_pop - * - * PARAMETERS: pop_count - Number of objects/entries to pop - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT - * deleted by this routine. - * - ******************************************************************************/ - -acpi_status -acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state) -{ - u32 i; - - ACPI_FUNCTION_NAME(ds_obj_stack_pop); - - for (i = 0; i < pop_count; i++) { - - /* Check for stack underflow */ - - if (walk_state->num_operands == 0) { - ACPI_ERROR((AE_INFO, - "Object stack underflow! Count=%X State=%p #Ops=%X", - pop_count, walk_state, - walk_state->num_operands)); - return (AE_STACK_UNDERFLOW); - } - - /* Just set the stack entry to null */ - - walk_state->num_operands--; - walk_state->operands[walk_state->num_operands] = NULL; - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", - pop_count, walk_state, walk_state->num_operands)); - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_obj_stack_pop_and_delete - * - * PARAMETERS: pop_count - Number of objects/entries to pop - * walk_state - Current Walk state - * - * RETURN: Status - * - * DESCRIPTION: Pop this walk's object stack and delete each object that is - * popped off. - * - ******************************************************************************/ - -void -acpi_ds_obj_stack_pop_and_delete(u32 pop_count, - struct acpi_walk_state *walk_state) -{ - s32 i; - union acpi_operand_object *obj_desc; - - ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); - - if (pop_count == 0) { - return; - } - - for (i = (s32) pop_count - 1; i >= 0; i--) { - if (walk_state->num_operands == 0) { - return; - } - - /* Pop the stack and delete an object if present in this stack entry */ - - walk_state->num_operands--; - obj_desc = walk_state->operands[i]; - if (obj_desc) { - acpi_ut_remove_reference(walk_state->operands[i]); - walk_state->operands[i] = NULL; - } - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", - pop_count, walk_state, walk_state->num_operands)); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_current_walk_state - * - * PARAMETERS: Thread - Get current active state for this Thread - * - * RETURN: Pointer to the current walk state - * - * DESCRIPTION: Get the walk state that is at the head of the list (the "current" - * walk state.) - * - ******************************************************************************/ - -struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state - *thread) -{ - ACPI_FUNCTION_NAME(ds_get_current_walk_state); - - if (!thread) { - return (NULL); - } - - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current WalkState %p\n", - thread->walk_state_list)); - - return (thread->walk_state_list); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_push_walk_state - * - * PARAMETERS: walk_state - State to push - * Thread - Thread state object - * - * RETURN: None - * - * DESCRIPTION: Place the Thread state at the head of the state list - * - ******************************************************************************/ - -void -acpi_ds_push_walk_state(struct acpi_walk_state *walk_state, - struct acpi_thread_state *thread) -{ - ACPI_FUNCTION_TRACE(ds_push_walk_state); - - walk_state->next = thread->walk_state_list; - thread->walk_state_list = walk_state; - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_pop_walk_state - * - * PARAMETERS: Thread - Current thread state - * - * RETURN: A walk_state object popped from the thread's stack - * - * DESCRIPTION: Remove and return the walkstate object that is at the head of - * the walk stack for the given walk list. NULL indicates that - * the list is empty. - * - ******************************************************************************/ - -struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) -{ - struct acpi_walk_state *walk_state; - - ACPI_FUNCTION_TRACE(ds_pop_walk_state); - - walk_state = thread->walk_state_list; - - if (walk_state) { - - /* Next walk state becomes the current walk state */ - - thread->walk_state_list = walk_state->next; - - /* - * Don't clear the NEXT field, this serves as an indicator - * that there is a parent WALK STATE - * Do Not: walk_state->Next = NULL; - */ - } - - return_PTR(walk_state); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_create_walk_state - * - * PARAMETERS: owner_id - ID for object creation - * Origin - Starting point for this walk - * method_desc - Method object - * Thread - Current thread state - * - * RETURN: Pointer to the new walk state. - * - * DESCRIPTION: Allocate and initialize a new walk state. The current walk - * state is set to this new state. - * - ******************************************************************************/ - -struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object - *origin, union acpi_operand_object - *method_desc, struct acpi_thread_state - *thread) -{ - struct acpi_walk_state *walk_state; - - ACPI_FUNCTION_TRACE(ds_create_walk_state); - - walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state)); - if (!walk_state) { - return_PTR(NULL); - } - - walk_state->descriptor_type = ACPI_DESC_TYPE_WALK; - walk_state->method_desc = method_desc; - walk_state->owner_id = owner_id; - walk_state->origin = origin; - walk_state->thread = thread; - - walk_state->parser_state.start_op = origin; - - /* Init the method args/local */ - -#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) - acpi_ds_method_data_init(walk_state); -#endif - - /* Put the new state at the head of the walk list */ - - if (thread) { - acpi_ds_push_walk_state(walk_state, thread); - } - - return_PTR(walk_state); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_init_aml_walk - * - * PARAMETERS: walk_state - New state to be initialized - * Op - Current parse op - * method_node - Control method NS node, if any - * aml_start - Start of AML - * aml_length - Length of AML - * Info - Method info block (params, etc.) - * pass_number - 1, 2, or 3 - * - * RETURN: Status - * - * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk - * - ******************************************************************************/ - -acpi_status -acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, - struct acpi_namespace_node *method_node, - u8 * aml_start, - u32 aml_length, - struct acpi_evaluate_info *info, u8 pass_number) -{ - acpi_status status; - struct acpi_parse_state *parser_state = &walk_state->parser_state; - union acpi_parse_object *extra_op; - - ACPI_FUNCTION_TRACE(ds_init_aml_walk); - - walk_state->parser_state.aml = - walk_state->parser_state.aml_start = aml_start; - walk_state->parser_state.aml_end = - walk_state->parser_state.pkg_end = aml_start + aml_length; - - /* The next_op of the next_walk will be the beginning of the method */ - - walk_state->next_op = NULL; - walk_state->pass_number = pass_number; - - if (info) { - walk_state->params = info->parameters; - walk_state->caller_return_desc = &info->return_object; - } - - status = acpi_ps_init_scope(&walk_state->parser_state, op); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (method_node) { - walk_state->parser_state.start_node = method_node; - walk_state->walk_type = ACPI_WALK_METHOD; - walk_state->method_node = method_node; - walk_state->method_desc = - acpi_ns_get_attached_object(method_node); - - /* Push start scope on scope stack and make it current */ - - status = - acpi_ds_scope_stack_push(method_node, ACPI_TYPE_METHOD, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Init the method arguments */ - - status = acpi_ds_method_data_init_args(walk_state->params, - ACPI_METHOD_NUM_ARGS, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } else { - /* - * Setup the current scope. - * Find a Named Op that has a namespace node associated with it. - * search upwards from this Op. Current scope is the first - * Op with a namespace node. - */ - extra_op = parser_state->start_op; - while (extra_op && !extra_op->common.node) { - extra_op = extra_op->common.parent; - } - - if (!extra_op) { - parser_state->start_node = NULL; - } else { - parser_state->start_node = extra_op->common.node; - } - - if (parser_state->start_node) { - - /* Push start scope on scope stack and make it current */ - - status = - acpi_ds_scope_stack_push(parser_state->start_node, - parser_state->start_node-> - type, walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - } - - status = acpi_ds_init_callbacks(walk_state, pass_number); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_delete_walk_state - * - * PARAMETERS: walk_state - State to delete - * - * RETURN: Status - * - * DESCRIPTION: Delete a walk state including all internal data structures - * - ******************************************************************************/ - -void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state); - - if (!walk_state) { - return; - } - - if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) { - ACPI_ERROR((AE_INFO, "%p is not a valid walk state", - walk_state)); - return; - } - - /* There should not be any open scopes */ - - if (walk_state->parser_state.scope) { - ACPI_ERROR((AE_INFO, "%p walk still has a scope list", - walk_state)); - acpi_ps_cleanup_scope(&walk_state->parser_state); - } - - /* Always must free any linked control states */ - - while (walk_state->control_state) { - state = walk_state->control_state; - walk_state->control_state = state->common.next; - - acpi_ut_delete_generic_state(state); - } - - /* Always must free any linked parse states */ - - while (walk_state->scope_info) { - state = walk_state->scope_info; - walk_state->scope_info = state->common.next; - - acpi_ut_delete_generic_state(state); - } - - /* Always must free any stacked result states */ - - while (walk_state->results) { - state = walk_state->results; - walk_state->results = state->common.next; - - acpi_ut_delete_generic_state(state); - } - - ACPI_FREE(walk_state); - return_VOID; -} diff --git a/drivers/acpi/events/Makefile b/drivers/acpi/events/Makefile deleted file mode 100644 index d29f2ee449cc..000000000000 --- a/drivers/acpi/events/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -obj-y := evevent.o evregion.o evsci.o evxfevnt.o \ - evmisc.o evrgnini.o evxface.o evxfregn.o \ - evgpe.o evgpeblk.o - -EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c deleted file mode 100644 index 86bf08365dad..000000000000 --- a/drivers/acpi/events/evevent.c +++ /dev/null @@ -1,313 +0,0 @@ -/****************************************************************************** - * - * Module Name: evevent - Fixed Event handling and dispatch - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_EVENTS -ACPI_MODULE_NAME("evevent") - -/* Local prototypes */ -static acpi_status acpi_ev_fixed_event_initialize(void); - -static u32 acpi_ev_fixed_event_dispatch(u32 event); - -/******************************************************************************* - * - * FUNCTION: acpi_ev_initialize_events - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE) - * - ******************************************************************************/ - -acpi_status acpi_ev_initialize_events(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_initialize_events); - - /* - * Initialize the Fixed and General Purpose Events. This is done prior to - * enabling SCIs to prevent interrupts from occurring before the handlers - * are installed. - */ - status = acpi_ev_fixed_event_initialize(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to initialize fixed events")); - return_ACPI_STATUS(status); - } - - status = acpi_ev_gpe_initialize(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to initialize general purpose events")); - return_ACPI_STATUS(status); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_fadt_gpes - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Completes initialization of the FADT-defined GPE blocks - * (0 and 1). This causes the _PRW methods to be run, so the HW - * must be fully initialized at this point, including global lock - * support. - * - ******************************************************************************/ - -acpi_status acpi_ev_install_fadt_gpes(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_install_fadt_gpes); - - /* Namespace must be locked */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* FADT GPE Block 0 */ - - (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device, - acpi_gbl_gpe_fadt_blocks[0]); - - /* FADT GPE Block 1 */ - - (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device, - acpi_gbl_gpe_fadt_blocks[1]); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_xrupt_handlers - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock - * - ******************************************************************************/ - -acpi_status acpi_ev_install_xrupt_handlers(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers); - - /* Install the SCI handler */ - - status = acpi_ev_install_sci_handler(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to install System Control Interrupt handler")); - return_ACPI_STATUS(status); - } - - /* Install the handler for the Global Lock */ - - status = acpi_ev_init_global_lock_handler(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to initialize Global Lock handler")); - return_ACPI_STATUS(status); - } - - acpi_gbl_events_initialized = TRUE; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_fixed_event_initialize - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Install the fixed event handlers and enable the fixed events. - * - ******************************************************************************/ - -static acpi_status acpi_ev_fixed_event_initialize(void) -{ - u32 i; - acpi_status status; - - /* - * Initialize the structure that keeps track of fixed event handlers and - * enable the fixed events. - */ - for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { - acpi_gbl_fixed_event_handlers[i].handler = NULL; - acpi_gbl_fixed_event_handlers[i].context = NULL; - - /* Enable the fixed event */ - - if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) { - status = - acpi_set_register(acpi_gbl_fixed_event_info[i]. - enable_register_id, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - } - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_fixed_event_detect - * - * PARAMETERS: None - * - * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED - * - * DESCRIPTION: Checks the PM status register for active fixed events - * - ******************************************************************************/ - -u32 acpi_ev_fixed_event_detect(void) -{ - u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; - u32 fixed_status; - u32 fixed_enable; - u32 i; - - ACPI_FUNCTION_NAME(ev_fixed_event_detect); - - /* - * Read the fixed feature status and enable registers, as all the cases - * depend on their values. Ignore errors here. - */ - (void)acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status); - (void)acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable); - - ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, - "Fixed Event Block: Enable %08X Status %08X\n", - fixed_enable, fixed_status)); - - /* - * Check for all possible Fixed Events and dispatch those that are active - */ - for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { - - /* Both the status and enable bits must be on for this event */ - - if ((fixed_status & acpi_gbl_fixed_event_info[i]. - status_bit_mask) - && (fixed_enable & acpi_gbl_fixed_event_info[i]. - enable_bit_mask)) { - - /* Found an active (signalled) event */ - acpi_os_fixed_event_count(i); - int_status |= acpi_ev_fixed_event_dispatch(i); - } - } - - return (int_status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_fixed_event_dispatch - * - * PARAMETERS: Event - Event type - * - * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED - * - * DESCRIPTION: Clears the status bit for the requested event, calls the - * handler that previously registered for the event. - * - ******************************************************************************/ - -static u32 acpi_ev_fixed_event_dispatch(u32 event) -{ - - ACPI_FUNCTION_ENTRY(); - - /* Clear the status bit */ - - (void)acpi_set_register(acpi_gbl_fixed_event_info[event]. - status_register_id, 1); - - /* - * Make sure we've got a handler. If not, report an error. The event is - * disabled to prevent further interrupts. - */ - if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { - (void)acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 0); - - ACPI_ERROR((AE_INFO, - "No installed handler for fixed event [%08X]", - event)); - - return (ACPI_INTERRUPT_NOT_HANDLED); - } - - /* Invoke the Fixed Event handler */ - - return ((acpi_gbl_fixed_event_handlers[event]. - handler) (acpi_gbl_fixed_event_handlers[event].context)); -} diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c deleted file mode 100644 index d9779608dbd7..000000000000 --- a/drivers/acpi/events/evgpe.c +++ /dev/null @@ -1,722 +0,0 @@ -/****************************************************************************** - * - * Module Name: evgpe - General Purpose Event handling and dispatch - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_EVENTS -ACPI_MODULE_NAME("evgpe") - -/* Local prototypes */ -static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context); - -/******************************************************************************* - * - * FUNCTION: acpi_ev_set_gpe_type - * - * PARAMETERS: gpe_event_info - GPE to set - * Type - New type - * - * RETURN: Status - * - * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run) - * - ******************************************************************************/ - -acpi_status -acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_set_gpe_type); - - /* Validate type and update register enable masks */ - - switch (type) { - case ACPI_GPE_TYPE_WAKE: - case ACPI_GPE_TYPE_RUNTIME: - case ACPI_GPE_TYPE_WAKE_RUN: - break; - - default: - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Disable the GPE if currently enabled */ - - status = acpi_ev_disable_gpe(gpe_event_info); - - /* Type was validated above */ - - gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */ - gpe_event_info->flags |= type; /* Insert type */ - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_update_gpe_enable_masks - * - * PARAMETERS: gpe_event_info - GPE to update - * Type - What to do: ACPI_GPE_DISABLE or - * ACPI_GPE_ENABLE - * - * RETURN: Status - * - * DESCRIPTION: Updates GPE register enable masks based on the GPE type - * - ******************************************************************************/ - -acpi_status -acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, - u8 type) -{ - struct acpi_gpe_register_info *gpe_register_info; - u8 register_bit; - - ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks); - - gpe_register_info = gpe_event_info->register_info; - if (!gpe_register_info) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - register_bit = (u8) - (1 << - (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); - - /* 1) Disable case. Simply clear all enable bits */ - - if (type == ACPI_GPE_DISABLE) { - ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, - register_bit); - ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit); - return_ACPI_STATUS(AE_OK); - } - - /* 2) Enable case. Set/Clear the appropriate enable bits */ - - switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { - case ACPI_GPE_TYPE_WAKE: - ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit); - ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit); - break; - - case ACPI_GPE_TYPE_RUNTIME: - ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, - register_bit); - ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit); - break; - - case ACPI_GPE_TYPE_WAKE_RUN: - ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit); - ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit); - break; - - default: - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_enable_gpe - * - * PARAMETERS: gpe_event_info - GPE to enable - * write_to_hardware - Enable now, or just mark data structs - * (WAKE GPEs should be deferred) - * - * RETURN: Status - * - * DESCRIPTION: Enable a GPE based on the GPE type - * - ******************************************************************************/ - -acpi_status -acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info, - u8 write_to_hardware) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_enable_gpe); - - /* Make sure HW enable masks are updated */ - - status = - acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_ENABLE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Mark wake-enabled or HW enable, or both */ - - switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { - case ACPI_GPE_TYPE_WAKE: - - ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); - break; - - case ACPI_GPE_TYPE_WAKE_RUN: - - ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); - - /*lint -fallthrough */ - - case ACPI_GPE_TYPE_RUNTIME: - - ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); - - if (write_to_hardware) { - - /* Clear the GPE (of stale events), then enable it */ - - status = acpi_hw_clear_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Enable the requested runtime GPE */ - - status = acpi_hw_write_gpe_enable_reg(gpe_event_info); - } - break; - - default: - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_disable_gpe - * - * PARAMETERS: gpe_event_info - GPE to disable - * - * RETURN: Status - * - * DESCRIPTION: Disable a GPE based on the GPE type - * - ******************************************************************************/ - -acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_disable_gpe); - - /* Make sure HW enable masks are updated */ - - status = - acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_DISABLE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Clear the appropriate enabled flags for this GPE */ - - switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { - case ACPI_GPE_TYPE_WAKE: - ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); - break; - - case ACPI_GPE_TYPE_WAKE_RUN: - ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); - - /* fallthrough */ - - case ACPI_GPE_TYPE_RUNTIME: - - /* Disable the requested runtime GPE */ - - ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); - break; - - default: - break; - } - - /* - * Even if we don't know the GPE type, make sure that we always - * disable it. low_disable_gpe will just clear the enable bit for this - * GPE and write it. It will not write out the current GPE enable mask, - * since this may inadvertently enable GPEs too early, if a rogue GPE has - * come in during ACPICA initialization - possibly as a result of AML or - * other code that has enabled the GPE. - */ - status = acpi_hw_low_disable_gpe(gpe_event_info); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_get_gpe_event_info - * - * PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1 - * gpe_number - Raw GPE number - * - * RETURN: A GPE event_info struct. NULL if not a valid GPE - * - * DESCRIPTION: Returns the event_info struct associated with this GPE. - * Validates the gpe_block and the gpe_number - * - * Should be called only when the GPE lists are semaphore locked - * and not subject to change. - * - ******************************************************************************/ - -struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, - u32 gpe_number) -{ - union acpi_operand_object *obj_desc; - struct acpi_gpe_block_info *gpe_block; - u32 i; - - ACPI_FUNCTION_ENTRY(); - - /* A NULL gpe_block means use the FADT-defined GPE block(s) */ - - if (!gpe_device) { - - /* Examine GPE Block 0 and 1 (These blocks are permanent) */ - - for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) { - gpe_block = acpi_gbl_gpe_fadt_blocks[i]; - if (gpe_block) { - if ((gpe_number >= gpe_block->block_base_number) - && (gpe_number < - gpe_block->block_base_number + - (gpe_block->register_count * 8))) { - return (&gpe_block-> - event_info[gpe_number - - gpe_block-> - block_base_number]); - } - } - } - - /* The gpe_number was not in the range of either FADT GPE block */ - - return (NULL); - } - - /* A Non-NULL gpe_device means this is a GPE Block Device */ - - obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *) - gpe_device); - if (!obj_desc || !obj_desc->device.gpe_block) { - return (NULL); - } - - gpe_block = obj_desc->device.gpe_block; - - if ((gpe_number >= gpe_block->block_base_number) && - (gpe_number < - gpe_block->block_base_number + (gpe_block->register_count * 8))) { - return (&gpe_block-> - event_info[gpe_number - gpe_block->block_base_number]); - } - - return (NULL); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_gpe_detect - * - * PARAMETERS: gpe_xrupt_list - Interrupt block for this interrupt. - * Can have multiple GPE blocks attached. - * - * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED - * - * DESCRIPTION: Detect if any GP events have occurred. This function is - * executed at interrupt level. - * - ******************************************************************************/ - -u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) -{ - acpi_status status; - struct acpi_gpe_block_info *gpe_block; - struct acpi_gpe_register_info *gpe_register_info; - u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; - u8 enabled_status_byte; - u32 status_reg; - u32 enable_reg; - acpi_cpu_flags flags; - u32 i; - u32 j; - - ACPI_FUNCTION_NAME(ev_gpe_detect); - - /* Check for the case where there are no GPEs */ - - if (!gpe_xrupt_list) { - return (int_status); - } - - /* - * We need to obtain the GPE lock for both the data structs and registers - * Note: Not necessary to obtain the hardware lock, since the GPE - * registers are owned by the gpe_lock. - */ - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - - /* Examine all GPE blocks attached to this interrupt level */ - - gpe_block = gpe_xrupt_list->gpe_block_list_head; - while (gpe_block) { - /* - * Read all of the 8-bit GPE status and enable registers in this GPE - * block, saving all of them. Find all currently active GP events. - */ - for (i = 0; i < gpe_block->register_count; i++) { - - /* Get the next status/enable pair */ - - gpe_register_info = &gpe_block->register_info[i]; - - /* Read the Status Register */ - - status = - acpi_read(&status_reg, - &gpe_register_info->status_address); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - /* Read the Enable Register */ - - status = - acpi_read(&enable_reg, - &gpe_register_info->enable_address); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, - "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n", - gpe_register_info->base_gpe_number, - status_reg, enable_reg)); - - /* Check if there is anything active at all in this register */ - - enabled_status_byte = (u8) (status_reg & enable_reg); - if (!enabled_status_byte) { - - /* No active GPEs in this register, move on */ - - continue; - } - - /* Now look at the individual GPEs in this byte register */ - - for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { - - /* Examine one GPE bit */ - - if (enabled_status_byte & (1 << j)) { - /* - * Found an active GPE. Dispatch the event to a handler - * or method. - */ - int_status |= - acpi_ev_gpe_dispatch(&gpe_block-> - event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number); - } - } - } - - gpe_block = gpe_block->next; - } - - unlock_and_exit: - - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - return (int_status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_asynch_execute_gpe_method - * - * PARAMETERS: Context (gpe_event_info) - Info for this GPE - * - * RETURN: None - * - * DESCRIPTION: Perform the actual execution of a GPE control method. This - * function is called from an invocation of acpi_os_execute and - * therefore does NOT execute at interrupt level - so that - * the control method itself is not executed in the context of - * an interrupt handler. - * - ******************************************************************************/ -static void acpi_ev_asynch_enable_gpe(void *context); - -static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) -{ - struct acpi_gpe_event_info *gpe_event_info = (void *)context; - acpi_status status; - struct acpi_gpe_event_info local_gpe_event_info; - struct acpi_evaluate_info *info; - - ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_VOID; - } - - /* Must revalidate the gpe_number/gpe_block */ - - if (!acpi_ev_valid_gpe_event(gpe_event_info)) { - status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); - return_VOID; - } - - /* Set the GPE flags for return to enabled state */ - - (void)acpi_ev_enable_gpe(gpe_event_info, FALSE); - - /* - * Take a snapshot of the GPE info for this level - we copy the info to - * prevent a race condition with remove_handler/remove_block. - */ - ACPI_MEMCPY(&local_gpe_event_info, gpe_event_info, - sizeof(struct acpi_gpe_event_info)); - - status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_VOID; - } - - /* - * Must check for control method type dispatch one more time to avoid a - * race with ev_gpe_install_handler - */ - if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == - ACPI_GPE_DISPATCH_METHOD) { - - /* Allocate the evaluation information block */ - - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); - if (!info) { - status = AE_NO_MEMORY; - } else { - /* - * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx - * control method that corresponds to this GPE - */ - info->prefix_node = - local_gpe_event_info.dispatch.method_node; - info->flags = ACPI_IGNORE_RETURN_VALUE; - - status = acpi_ns_evaluate(info); - ACPI_FREE(info); - } - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "while evaluating GPE method [%4.4s]", - acpi_ut_get_node_name - (local_gpe_event_info.dispatch. - method_node))); - } - } - /* Defer enabling of GPE until all notify handlers are done */ - acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe, - gpe_event_info); - return_VOID; -} - -static void acpi_ev_asynch_enable_gpe(void *context) -{ - struct acpi_gpe_event_info *gpe_event_info = context; - acpi_status status; - if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == - ACPI_GPE_LEVEL_TRIGGERED) { - /* - * GPE is level-triggered, we clear the GPE status bit after handling - * the event. - */ - status = acpi_hw_clear_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - return_VOID; - } - } - - /* Enable this GPE */ - (void)acpi_hw_write_gpe_enable_reg(gpe_event_info); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_gpe_dispatch - * - * PARAMETERS: gpe_event_info - Info for this GPE - * gpe_number - Number relative to the parent GPE block - * - * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED - * - * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) - * or method (e.g. _Lxx/_Exx) handler. - * - * This function executes at interrupt level. - * - ******************************************************************************/ - -u32 -acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_gpe_dispatch); - - acpi_os_gpe_count(gpe_number); - - /* - * If edge-triggered, clear the GPE status bit now. Note that - * level-triggered events are cleared after the GPE is serviced. - */ - if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == - ACPI_GPE_EDGE_TRIGGERED) { - status = acpi_hw_clear_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to clear GPE[%2X]", - gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); - } - } - - /* - * Dispatch the GPE to either an installed handler, or the control method - * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke - * it and do not attempt to run the method. If there is neither a handler - * nor a method, we disable this GPE to prevent further such pointless - * events from firing. - */ - switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { - case ACPI_GPE_DISPATCH_HANDLER: - - /* - * Invoke the installed handler (at interrupt level) - * Ignore return status for now. - * TBD: leave GPE disabled on error? - */ - (void)gpe_event_info->dispatch.handler->address(gpe_event_info-> - dispatch. - handler-> - context); - - /* It is now safe to clear level-triggered events. */ - - if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == - ACPI_GPE_LEVEL_TRIGGERED) { - status = acpi_hw_clear_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to clear GPE[%2X]", - gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); - } - } - break; - - case ACPI_GPE_DISPATCH_METHOD: - - /* - * Disable the GPE, so it doesn't keep firing before the method has a - * chance to run (it runs asynchronously with interrupts enabled). - */ - status = acpi_ev_disable_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to disable GPE[%2X]", - gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); - } - - /* - * Execute the method associated with the GPE - * NOTE: Level-triggered GPEs are cleared after the method completes. - */ - status = acpi_os_execute(OSL_GPE_HANDLER, - acpi_ev_asynch_execute_gpe_method, - gpe_event_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to queue handler for GPE[%2X] - event disabled", - gpe_number)); - } - break; - - default: - - /* No handler or method to run! */ - - ACPI_ERROR((AE_INFO, - "No handler or method for GPE[%2X], disabling event", - gpe_number)); - - /* - * Disable the GPE. The GPE will remain disabled until the ACPICA - * Core Subsystem is restarted, or a handler is installed. - */ - status = acpi_ev_disable_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to disable GPE[%2X]", - gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); - } - break; - } - - return_UINT32(ACPI_INTERRUPT_HANDLED); -} diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c deleted file mode 100644 index 2a8d1856038f..000000000000 --- a/drivers/acpi/events/evgpeblk.c +++ /dev/null @@ -1,1227 +0,0 @@ -/****************************************************************************** - * - * Module Name: evgpeblk - GPE block creation and initialization. - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_EVENTS -ACPI_MODULE_NAME("evgpeblk") - -/* Local prototypes */ -static acpi_status -acpi_ev_save_method_info(acpi_handle obj_handle, - u32 level, void *obj_desc, void **return_value); - -static acpi_status -acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, - u32 level, void *info, void **return_value); - -static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 - interrupt_number); - -static acpi_status -acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt); - -static acpi_status -acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, - u32 interrupt_number); - -static acpi_status -acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block); - -/******************************************************************************* - * - * FUNCTION: acpi_ev_valid_gpe_event - * - * PARAMETERS: gpe_event_info - Info for this GPE - * - * RETURN: TRUE if the gpe_event is valid - * - * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL. - * Should be called only when the GPE lists are semaphore locked - * and not subject to change. - * - ******************************************************************************/ - -u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info) -{ - struct acpi_gpe_xrupt_info *gpe_xrupt_block; - struct acpi_gpe_block_info *gpe_block; - - ACPI_FUNCTION_ENTRY(); - - /* No need for spin lock since we are not changing any list elements */ - - /* Walk the GPE interrupt levels */ - - gpe_xrupt_block = acpi_gbl_gpe_xrupt_list_head; - while (gpe_xrupt_block) { - gpe_block = gpe_xrupt_block->gpe_block_list_head; - - /* Walk the GPE blocks on this interrupt level */ - - while (gpe_block) { - if ((&gpe_block->event_info[0] <= gpe_event_info) && - (&gpe_block-> - event_info[((acpi_size) gpe_block-> - register_count) * 8] > - gpe_event_info)) { - return (TRUE); - } - - gpe_block = gpe_block->next; - } - - gpe_xrupt_block = gpe_xrupt_block->next; - } - - return (FALSE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_walk_gpe_list - * - * PARAMETERS: gpe_walk_callback - Routine called for each GPE block - * Context - Value passed to callback - * - * RETURN: Status - * - * DESCRIPTION: Walk the GPE lists. - * - ******************************************************************************/ - -acpi_status -acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context) -{ - struct acpi_gpe_block_info *gpe_block; - struct acpi_gpe_xrupt_info *gpe_xrupt_info; - acpi_status status = AE_OK; - acpi_cpu_flags flags; - - ACPI_FUNCTION_TRACE(ev_walk_gpe_list); - - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - - /* Walk the interrupt level descriptor list */ - - gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; - while (gpe_xrupt_info) { - - /* Walk all Gpe Blocks attached to this interrupt level */ - - gpe_block = gpe_xrupt_info->gpe_block_list_head; - while (gpe_block) { - - /* One callback per GPE block */ - - status = - gpe_walk_callback(gpe_xrupt_info, gpe_block, - context); - if (ACPI_FAILURE(status)) { - if (status == AE_CTRL_END) { /* Callback abort */ - status = AE_OK; - } - goto unlock_and_exit; - } - - gpe_block = gpe_block->next; - } - - gpe_xrupt_info = gpe_xrupt_info->next; - } - - unlock_and_exit: - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_delete_gpe_handlers - * - * PARAMETERS: gpe_xrupt_info - GPE Interrupt info - * gpe_block - Gpe Block info - * - * RETURN: Status - * - * DESCRIPTION: Delete all Handler objects found in the GPE data structs. - * Used only prior to termination. - * - ******************************************************************************/ - -acpi_status -acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, - void *context) -{ - struct acpi_gpe_event_info *gpe_event_info; - u32 i; - u32 j; - - ACPI_FUNCTION_TRACE(ev_delete_gpe_handlers); - - /* Examine each GPE Register within the block */ - - for (i = 0; i < gpe_block->register_count; i++) { - - /* Now look at the individual GPEs in this byte register */ - - for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { - gpe_event_info = - &gpe_block-> - event_info[((acpi_size) i * - ACPI_GPE_REGISTER_WIDTH) + j]; - - if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == - ACPI_GPE_DISPATCH_HANDLER) { - ACPI_FREE(gpe_event_info->dispatch.handler); - gpe_event_info->dispatch.handler = NULL; - gpe_event_info->flags &= - ~ACPI_GPE_DISPATCH_MASK; - } - } - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_save_method_info - * - * PARAMETERS: Callback from walk_namespace - * - * RETURN: Status - * - * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a - * control method under the _GPE portion of the namespace. - * Extract the name and GPE type from the object, saving this - * information for quick lookup during GPE dispatch - * - * The name of each GPE control method is of the form: - * "_Lxx" or "_Exx" - * Where: - * L - means that the GPE is level triggered - * E - means that the GPE is edge triggered - * xx - is the GPE number [in HEX] - * - ******************************************************************************/ - -static acpi_status -acpi_ev_save_method_info(acpi_handle obj_handle, - u32 level, void *obj_desc, void **return_value) -{ - struct acpi_gpe_block_info *gpe_block = (void *)obj_desc; - struct acpi_gpe_event_info *gpe_event_info; - u32 gpe_number; - char name[ACPI_NAME_SIZE + 1]; - u8 type; - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_save_method_info); - - /* - * _Lxx and _Exx GPE method support - * - * 1) Extract the name from the object and convert to a string - */ - ACPI_MOVE_32_TO_32(name, - &((struct acpi_namespace_node *)obj_handle)->name. - integer); - name[ACPI_NAME_SIZE] = 0; - - /* - * 2) Edge/Level determination is based on the 2nd character - * of the method name - * - * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE - * if a _PRW object is found that points to this GPE. - */ - switch (name[1]) { - case 'L': - type = ACPI_GPE_LEVEL_TRIGGERED; - break; - - case 'E': - type = ACPI_GPE_EDGE_TRIGGERED; - break; - - default: - /* Unknown method type, just ignore it! */ - - ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "Ignoring unknown GPE method type: %s (name not of form _Lxx or _Exx)", - name)); - return_ACPI_STATUS(AE_OK); - } - - /* Convert the last two characters of the name to the GPE Number */ - - gpe_number = ACPI_STRTOUL(&name[2], NULL, 16); - if (gpe_number == ACPI_UINT32_MAX) { - - /* Conversion failed; invalid method, just ignore it */ - - ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)", - name)); - return_ACPI_STATUS(AE_OK); - } - - /* Ensure that we have a valid GPE number for this GPE block */ - - if ((gpe_number < gpe_block->block_base_number) || - (gpe_number >= - (gpe_block->block_base_number + - (gpe_block->register_count * 8)))) { - /* - * Not valid for this GPE block, just ignore it. However, it may be - * valid for a different GPE block, since GPE0 and GPE1 methods both - * appear under \_GPE. - */ - return_ACPI_STATUS(AE_OK); - } - - /* - * Now we can add this information to the gpe_event_info block for use - * during dispatch of this GPE. Default type is RUNTIME, although this may - * change when the _PRW methods are executed later. - */ - gpe_event_info = - &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; - - gpe_event_info->flags = (u8) - (type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME); - - gpe_event_info->dispatch.method_node = - (struct acpi_namespace_node *)obj_handle; - - /* Update enable mask, but don't enable the HW GPE as of yet */ - - status = acpi_ev_enable_gpe(gpe_event_info, FALSE); - - ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "Registered GPE method %s as GPE number 0x%.2X\n", - name, gpe_number)); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_match_prw_and_gpe - * - * PARAMETERS: Callback from walk_namespace - * - * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is - * not aborted on a single _PRW failure. - * - * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a - * Device. Run the _PRW method. If present, extract the GPE - * number and mark the GPE as a WAKE GPE. - * - ******************************************************************************/ - -static acpi_status -acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, - u32 level, void *info, void **return_value) -{ - struct acpi_gpe_walk_info *gpe_info = (void *)info; - struct acpi_namespace_node *gpe_device; - struct acpi_gpe_block_info *gpe_block; - struct acpi_namespace_node *target_gpe_device; - struct acpi_gpe_event_info *gpe_event_info; - union acpi_operand_object *pkg_desc; - union acpi_operand_object *obj_desc; - u32 gpe_number; - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_match_prw_and_gpe); - - /* Check for a _PRW method under this device */ - - status = acpi_ut_evaluate_object(obj_handle, METHOD_NAME__PRW, - ACPI_BTYPE_PACKAGE, &pkg_desc); - if (ACPI_FAILURE(status)) { - - /* Ignore all errors from _PRW, we don't want to abort the subsystem */ - - return_ACPI_STATUS(AE_OK); - } - - /* The returned _PRW package must have at least two elements */ - - if (pkg_desc->package.count < 2) { - goto cleanup; - } - - /* Extract pointers from the input context */ - - gpe_device = gpe_info->gpe_device; - gpe_block = gpe_info->gpe_block; - - /* - * The _PRW object must return a package, we are only interested in the - * first element - */ - obj_desc = pkg_desc->package.elements[0]; - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { - - /* Use FADT-defined GPE device (from definition of _PRW) */ - - target_gpe_device = acpi_gbl_fadt_gpe_device; - - /* Integer is the GPE number in the FADT described GPE blocks */ - - gpe_number = (u32) obj_desc->integer.value; - } else if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { - - /* Package contains a GPE reference and GPE number within a GPE block */ - - if ((obj_desc->package.count < 2) || - (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[0]) != - ACPI_TYPE_LOCAL_REFERENCE) - || (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[1]) != - ACPI_TYPE_INTEGER)) { - goto cleanup; - } - - /* Get GPE block reference and decode */ - - target_gpe_device = - obj_desc->package.elements[0]->reference.node; - gpe_number = (u32) obj_desc->package.elements[1]->integer.value; - } else { - /* Unknown type, just ignore it */ - - goto cleanup; - } - - /* - * Is this GPE within this block? - * - * TRUE if and only if these conditions are true: - * 1) The GPE devices match. - * 2) The GPE index(number) is within the range of the Gpe Block - * associated with the GPE device. - */ - if ((gpe_device == target_gpe_device) && - (gpe_number >= gpe_block->block_base_number) && - (gpe_number < - gpe_block->block_base_number + (gpe_block->register_count * 8))) { - gpe_event_info = - &gpe_block->event_info[gpe_number - - gpe_block->block_base_number]; - - /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ - - gpe_event_info->flags &= - ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED); - - status = - acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - status = - acpi_ev_update_gpe_enable_masks(gpe_event_info, - ACPI_GPE_DISABLE); - } - - cleanup: - acpi_ut_remove_reference(pkg_desc); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_get_gpe_xrupt_block - * - * PARAMETERS: interrupt_number - Interrupt for a GPE block - * - * RETURN: A GPE interrupt block - * - * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt - * block per unique interrupt level used for GPEs. Should be - * called only when the GPE lists are semaphore locked and not - * subject to change. - * - ******************************************************************************/ - -static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 - interrupt_number) -{ - struct acpi_gpe_xrupt_info *next_gpe_xrupt; - struct acpi_gpe_xrupt_info *gpe_xrupt; - acpi_status status; - acpi_cpu_flags flags; - - ACPI_FUNCTION_TRACE(ev_get_gpe_xrupt_block); - - /* No need for lock since we are not changing any list elements here */ - - next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head; - while (next_gpe_xrupt) { - if (next_gpe_xrupt->interrupt_number == interrupt_number) { - return_PTR(next_gpe_xrupt); - } - - next_gpe_xrupt = next_gpe_xrupt->next; - } - - /* Not found, must allocate a new xrupt descriptor */ - - gpe_xrupt = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_xrupt_info)); - if (!gpe_xrupt) { - return_PTR(NULL); - } - - gpe_xrupt->interrupt_number = interrupt_number; - - /* Install new interrupt descriptor with spin lock */ - - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - if (acpi_gbl_gpe_xrupt_list_head) { - next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head; - while (next_gpe_xrupt->next) { - next_gpe_xrupt = next_gpe_xrupt->next; - } - - next_gpe_xrupt->next = gpe_xrupt; - gpe_xrupt->previous = next_gpe_xrupt; - } else { - acpi_gbl_gpe_xrupt_list_head = gpe_xrupt; - } - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - - /* Install new interrupt handler if not SCI_INT */ - - if (interrupt_number != acpi_gbl_FADT.sci_interrupt) { - status = acpi_os_install_interrupt_handler(interrupt_number, - acpi_ev_gpe_xrupt_handler, - gpe_xrupt); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not install GPE interrupt handler at level 0x%X", - interrupt_number)); - return_PTR(NULL); - } - } - - return_PTR(gpe_xrupt); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_delete_gpe_xrupt - * - * PARAMETERS: gpe_xrupt - A GPE interrupt info block - * - * RETURN: Status - * - * DESCRIPTION: Remove and free a gpe_xrupt block. Remove an associated - * interrupt handler if not the SCI interrupt. - * - ******************************************************************************/ - -static acpi_status -acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt) -{ - acpi_status status; - acpi_cpu_flags flags; - - ACPI_FUNCTION_TRACE(ev_delete_gpe_xrupt); - - /* We never want to remove the SCI interrupt handler */ - - if (gpe_xrupt->interrupt_number == acpi_gbl_FADT.sci_interrupt) { - gpe_xrupt->gpe_block_list_head = NULL; - return_ACPI_STATUS(AE_OK); - } - - /* Disable this interrupt */ - - status = - acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number, - acpi_ev_gpe_xrupt_handler); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Unlink the interrupt block with lock */ - - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - if (gpe_xrupt->previous) { - gpe_xrupt->previous->next = gpe_xrupt->next; - } else { - /* No previous, update list head */ - - acpi_gbl_gpe_xrupt_list_head = gpe_xrupt->next; - } - - if (gpe_xrupt->next) { - gpe_xrupt->next->previous = gpe_xrupt->previous; - } - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - - /* Free the block */ - - ACPI_FREE(gpe_xrupt); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_gpe_block - * - * PARAMETERS: gpe_block - New GPE block - * interrupt_number - Xrupt to be associated with this - * GPE block - * - * RETURN: Status - * - * DESCRIPTION: Install new GPE block with mutex support - * - ******************************************************************************/ - -static acpi_status -acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, - u32 interrupt_number) -{ - struct acpi_gpe_block_info *next_gpe_block; - struct acpi_gpe_xrupt_info *gpe_xrupt_block; - acpi_status status; - acpi_cpu_flags flags; - - ACPI_FUNCTION_TRACE(ev_install_gpe_block); - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block(interrupt_number); - if (!gpe_xrupt_block) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - /* Install the new block at the end of the list with lock */ - - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - if (gpe_xrupt_block->gpe_block_list_head) { - next_gpe_block = gpe_xrupt_block->gpe_block_list_head; - while (next_gpe_block->next) { - next_gpe_block = next_gpe_block->next; - } - - next_gpe_block->next = gpe_block; - gpe_block->previous = next_gpe_block; - } else { - gpe_xrupt_block->gpe_block_list_head = gpe_block; - } - - gpe_block->xrupt_block = gpe_xrupt_block; - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - - unlock_and_exit: - status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_delete_gpe_block - * - * PARAMETERS: gpe_block - Existing GPE block - * - * RETURN: Status - * - * DESCRIPTION: Remove a GPE block - * - ******************************************************************************/ - -acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) -{ - acpi_status status; - acpi_cpu_flags flags; - - ACPI_FUNCTION_TRACE(ev_install_gpe_block); - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Disable all GPEs in this block */ - - status = - acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block, NULL); - - if (!gpe_block->previous && !gpe_block->next) { - - /* This is the last gpe_block on this interrupt */ - - status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - } else { - /* Remove the block on this interrupt with lock */ - - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - if (gpe_block->previous) { - gpe_block->previous->next = gpe_block->next; - } else { - gpe_block->xrupt_block->gpe_block_list_head = - gpe_block->next; - } - - if (gpe_block->next) { - gpe_block->next->previous = gpe_block->previous; - } - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - } - - acpi_current_gpe_count -= - gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH; - - /* Free the gpe_block */ - - ACPI_FREE(gpe_block->register_info); - ACPI_FREE(gpe_block->event_info); - ACPI_FREE(gpe_block); - - unlock_and_exit: - status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_create_gpe_info_blocks - * - * PARAMETERS: gpe_block - New GPE block - * - * RETURN: Status - * - * DESCRIPTION: Create the register_info and event_info blocks for this GPE block - * - ******************************************************************************/ - -static acpi_status -acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) -{ - struct acpi_gpe_register_info *gpe_register_info = NULL; - struct acpi_gpe_event_info *gpe_event_info = NULL; - struct acpi_gpe_event_info *this_event; - struct acpi_gpe_register_info *this_register; - u32 i; - u32 j; - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks); - - /* Allocate the GPE register information block */ - - gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block-> - register_count * - sizeof(struct - acpi_gpe_register_info)); - if (!gpe_register_info) { - ACPI_ERROR((AE_INFO, - "Could not allocate the GpeRegisterInfo table")); - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* - * Allocate the GPE event_info block. There are eight distinct GPEs - * per register. Initialization to zeros is sufficient. - */ - gpe_event_info = ACPI_ALLOCATE_ZEROED(((acpi_size) gpe_block-> - register_count * - ACPI_GPE_REGISTER_WIDTH) * - sizeof(struct - acpi_gpe_event_info)); - if (!gpe_event_info) { - ACPI_ERROR((AE_INFO, - "Could not allocate the GpeEventInfo table")); - status = AE_NO_MEMORY; - goto error_exit; - } - - /* Save the new Info arrays in the GPE block */ - - gpe_block->register_info = gpe_register_info; - gpe_block->event_info = gpe_event_info; - - /* - * Initialize the GPE Register and Event structures. A goal of these - * tables is to hide the fact that there are two separate GPE register - * sets in a given GPE hardware block, the status registers occupy the - * first half, and the enable registers occupy the second half. - */ - this_register = gpe_register_info; - this_event = gpe_event_info; - - for (i = 0; i < gpe_block->register_count; i++) { - - /* Init the register_info for this GPE register (8 GPEs) */ - - this_register->base_gpe_number = - (u8) (gpe_block->block_base_number + - (i * ACPI_GPE_REGISTER_WIDTH)); - - this_register->status_address.address = - gpe_block->block_address.address + i; - - this_register->enable_address.address = - gpe_block->block_address.address + i + - gpe_block->register_count; - - this_register->status_address.space_id = - gpe_block->block_address.space_id; - this_register->enable_address.space_id = - gpe_block->block_address.space_id; - this_register->status_address.bit_width = - ACPI_GPE_REGISTER_WIDTH; - this_register->enable_address.bit_width = - ACPI_GPE_REGISTER_WIDTH; - this_register->status_address.bit_offset = 0; - this_register->enable_address.bit_offset = 0; - - /* Init the event_info for each GPE within this register */ - - for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { - this_event->gpe_number = - (u8) (this_register->base_gpe_number + j); - this_event->register_info = this_register; - this_event++; - } - - /* Disable all GPEs within this register */ - - status = acpi_write(0x00, &this_register->enable_address); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - - /* Clear any pending GPE events within this register */ - - status = acpi_write(0xFF, &this_register->status_address); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - - this_register++; - } - - return_ACPI_STATUS(AE_OK); - - error_exit: - if (gpe_register_info) { - ACPI_FREE(gpe_register_info); - } - if (gpe_event_info) { - ACPI_FREE(gpe_event_info); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_create_gpe_block - * - * PARAMETERS: gpe_device - Handle to the parent GPE block - * gpe_block_address - Address and space_iD - * register_count - Number of GPE register pairs in the block - * gpe_block_base_number - Starting GPE number for the block - * interrupt_number - H/W interrupt for the block - * return_gpe_block - Where the new block descriptor is returned - * - * RETURN: Status - * - * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within - * the block are disabled at exit. - * Note: Assumes namespace is locked. - * - ******************************************************************************/ - -acpi_status -acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, - struct acpi_generic_address *gpe_block_address, - u32 register_count, - u8 gpe_block_base_number, - u32 interrupt_number, - struct acpi_gpe_block_info **return_gpe_block) -{ - acpi_status status; - struct acpi_gpe_block_info *gpe_block; - - ACPI_FUNCTION_TRACE(ev_create_gpe_block); - - if (!register_count) { - return_ACPI_STATUS(AE_OK); - } - - /* Allocate a new GPE block */ - - gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info)); - if (!gpe_block) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Initialize the new GPE block */ - - gpe_block->node = gpe_device; - gpe_block->register_count = register_count; - gpe_block->block_base_number = gpe_block_base_number; - - ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address, - sizeof(struct acpi_generic_address)); - - /* - * Create the register_info and event_info sub-structures - * Note: disables and clears all GPEs in the block - */ - status = acpi_ev_create_gpe_info_blocks(gpe_block); - if (ACPI_FAILURE(status)) { - ACPI_FREE(gpe_block); - return_ACPI_STATUS(status); - } - - /* Install the new block in the global lists */ - - status = acpi_ev_install_gpe_block(gpe_block, interrupt_number); - if (ACPI_FAILURE(status)) { - ACPI_FREE(gpe_block); - return_ACPI_STATUS(status); - } - - /* Find all GPE methods (_Lxx, _Exx) for this block */ - - status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, - ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, - acpi_ev_save_method_info, gpe_block, - NULL); - - /* Return the new block */ - - if (return_gpe_block) { - (*return_gpe_block) = gpe_block; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", - (u32) gpe_block->block_base_number, - (u32) (gpe_block->block_base_number + - ((gpe_block->register_count * - ACPI_GPE_REGISTER_WIDTH) - 1)), - gpe_device->name.ascii, gpe_block->register_count, - interrupt_number)); - - /* Update global count of currently available GPEs */ - - acpi_current_gpe_count += register_count * ACPI_GPE_REGISTER_WIDTH; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_initialize_gpe_block - * - * PARAMETERS: gpe_device - Handle to the parent GPE block - * gpe_block - Gpe Block info - * - * RETURN: Status - * - * DESCRIPTION: Initialize and enable a GPE block. First find and run any - * _PRT methods associated with the block, then enable the - * appropriate GPEs. - * Note: Assumes namespace is locked. - * - ******************************************************************************/ - -acpi_status -acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, - struct acpi_gpe_block_info *gpe_block) -{ - acpi_status status; - struct acpi_gpe_event_info *gpe_event_info; - struct acpi_gpe_walk_info gpe_info; - u32 wake_gpe_count; - u32 gpe_enabled_count; - u32 i; - u32 j; - - ACPI_FUNCTION_TRACE(ev_initialize_gpe_block); - - /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */ - - if (!gpe_block) { - return_ACPI_STATUS(AE_OK); - } - - /* - * Runtime option: Should wake GPEs be enabled at runtime? The default - * is no, they should only be enabled just as the machine goes to sleep. - */ - if (acpi_gbl_leave_wake_gpes_disabled) { - /* - * Differentiate runtime vs wake GPEs, via the _PRW control methods. - * Each GPE that has one or more _PRWs that reference it is by - * definition a wake GPE and will not be enabled while the machine - * is running. - */ - gpe_info.gpe_block = gpe_block; - gpe_info.gpe_device = gpe_device; - - status = - acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, - acpi_ev_match_prw_and_gpe, &gpe_info, - NULL); - } - - /* - * Enable all GPEs in this block that have these attributes: - * 1) are "runtime" or "run/wake" GPEs, and - * 2) have a corresponding _Lxx or _Exx method - * - * Any other GPEs within this block must be enabled via the acpi_enable_gpe() - * external interface. - */ - wake_gpe_count = 0; - gpe_enabled_count = 0; - - for (i = 0; i < gpe_block->register_count; i++) { - for (j = 0; j < 8; j++) { - - /* Get the info block for this particular GPE */ - - gpe_event_info = - &gpe_block-> - event_info[((acpi_size) i * - ACPI_GPE_REGISTER_WIDTH) + j]; - - if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == - ACPI_GPE_DISPATCH_METHOD) - && (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) { - gpe_enabled_count++; - } - - if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) { - wake_gpe_count++; - } - } - } - - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "Found %u Wake, Enabled %u Runtime GPEs in this block\n", - wake_gpe_count, gpe_enabled_count)); - - /* Enable all valid runtime GPEs found above */ - - status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block, NULL); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Could not enable GPEs in GpeBlock %p", - gpe_block)); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_gpe_initialize - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Initialize the GPE data structures - * - ******************************************************************************/ - -acpi_status acpi_ev_gpe_initialize(void) -{ - u32 register_count0 = 0; - u32 register_count1 = 0; - u32 gpe_number_max = 0; - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_gpe_initialize); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Initialize the GPE Block(s) defined in the FADT - * - * Why the GPE register block lengths are divided by 2: From the ACPI Spec, - * section "General-Purpose Event Registers", we have: - * - * "Each register block contains two registers of equal length - * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the - * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN - * The length of the GPE1_STS and GPE1_EN registers is equal to - * half the GPE1_LEN. If a generic register block is not supported - * then its respective block pointer and block length values in the - * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need - * to be the same size." - */ - - /* - * Determine the maximum GPE number for this machine. - * - * Note: both GPE0 and GPE1 are optional, and either can exist without - * the other. - * - * If EITHER the register length OR the block address are zero, then that - * particular block is not supported. - */ - if (acpi_gbl_FADT.gpe0_block_length && - acpi_gbl_FADT.xgpe0_block.address) { - - /* GPE block 0 exists (has both length and address > 0) */ - - register_count0 = (u16) (acpi_gbl_FADT.gpe0_block_length / 2); - - gpe_number_max = - (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1; - - /* Install GPE Block 0 */ - - status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, - &acpi_gbl_FADT.xgpe0_block, - register_count0, 0, - acpi_gbl_FADT.sci_interrupt, - &acpi_gbl_gpe_fadt_blocks[0]); - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not create GPE Block 0")); - } - } - - if (acpi_gbl_FADT.gpe1_block_length && - acpi_gbl_FADT.xgpe1_block.address) { - - /* GPE block 1 exists (has both length and address > 0) */ - - register_count1 = (u16) (acpi_gbl_FADT.gpe1_block_length / 2); - - /* Check for GPE0/GPE1 overlap (if both banks exist) */ - - if ((register_count0) && - (gpe_number_max >= acpi_gbl_FADT.gpe1_base)) { - ACPI_ERROR((AE_INFO, - "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1", - gpe_number_max, acpi_gbl_FADT.gpe1_base, - acpi_gbl_FADT.gpe1_base + - ((register_count1 * - ACPI_GPE_REGISTER_WIDTH) - 1))); - - /* Ignore GPE1 block by setting the register count to zero */ - - register_count1 = 0; - } else { - /* Install GPE Block 1 */ - - status = - acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, - &acpi_gbl_FADT.xgpe1_block, - register_count1, - acpi_gbl_FADT.gpe1_base, - acpi_gbl_FADT. - sci_interrupt, - &acpi_gbl_gpe_fadt_blocks - [1]); - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not create GPE Block 1")); - } - - /* - * GPE0 and GPE1 do not have to be contiguous in the GPE number - * space. However, GPE0 always starts at GPE number zero. - */ - gpe_number_max = acpi_gbl_FADT.gpe1_base + - ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1); - } - } - - /* Exit if there are no GPE registers */ - - if ((register_count0 + register_count1) == 0) { - - /* GPEs are not required by ACPI, this is OK */ - - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "There are no GPE blocks defined in the FADT\n")); - status = AE_OK; - goto cleanup; - } - - /* Check for Max GPE number out-of-range */ - - if (gpe_number_max > ACPI_GPE_MAX) { - ACPI_ERROR((AE_INFO, - "Maximum GPE number from FADT is too large: 0x%X", - gpe_number_max)); - status = AE_BAD_VALUE; - goto cleanup; - } - - cleanup: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c deleted file mode 100644 index 16f2c1a00167..000000000000 --- a/drivers/acpi/events/evmisc.c +++ /dev/null @@ -1,621 +0,0 @@ -/****************************************************************************** - * - * Module Name: evmisc - Miscellaneous event manager support functions - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EVENTS -ACPI_MODULE_NAME("evmisc") - -/* Local prototypes */ -static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); - -static u32 acpi_ev_global_lock_handler(void *context); - -static acpi_status acpi_ev_remove_global_lock_handler(void); - -/******************************************************************************* - * - * FUNCTION: acpi_ev_is_notify_object - * - * PARAMETERS: Node - Node to check - * - * RETURN: TRUE if notifies allowed on this object - * - * DESCRIPTION: Check type of node for a object that supports notifies. - * - * TBD: This could be replaced by a flag bit in the node. - * - ******************************************************************************/ - -u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node) -{ - switch (node->type) { - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_THERMAL: - /* - * These are the ONLY objects that can receive ACPI notifications - */ - return (TRUE); - - default: - return (FALSE); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_queue_notify_request - * - * PARAMETERS: Node - NS node for the notified object - * notify_value - Value from the Notify() request - * - * RETURN: Status - * - * DESCRIPTION: Dispatch a device notification event to a previously - * installed handler. - * - ******************************************************************************/ - -acpi_status -acpi_ev_queue_notify_request(struct acpi_namespace_node * node, - u32 notify_value) -{ - union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj = NULL; - union acpi_generic_state *notify_info; - acpi_status status = AE_OK; - - ACPI_FUNCTION_NAME(ev_queue_notify_request); - - /* - * For value 3 (Ejection Request), some device method may need to be run. - * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need - * to be run. - * For value 0x80 (Status Change) on the power button or sleep button, - * initiate soft-off or sleep operation? - */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", - acpi_ut_get_node_name(node), node, notify_value, - acpi_ut_get_notify_name(notify_value))); - - /* Get the notify object attached to the NS Node */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - - /* We have the notify object, Get the right handler */ - - switch (node->type) { - - /* Notify allowed only on these types */ - - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_THERMAL: - case ACPI_TYPE_PROCESSOR: - - if (notify_value <= ACPI_MAX_SYS_NOTIFY) { - handler_obj = - obj_desc->common_notify.system_notify; - } else { - handler_obj = - obj_desc->common_notify.device_notify; - } - break; - - default: - - /* All other types are not supported */ - - return (AE_TYPE); - } - } - - /* - * If there is any handler to run, schedule the dispatcher. - * Check for: - * 1) Global system notify handler - * 2) Global device notify handler - * 3) Per-device notify handler - */ - if ((acpi_gbl_system_notify.handler - && (notify_value <= ACPI_MAX_SYS_NOTIFY)) - || (acpi_gbl_device_notify.handler - && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { - notify_info = acpi_ut_create_generic_state(); - if (!notify_info) { - return (AE_NO_MEMORY); - } - - if (!handler_obj) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Executing system notify handler for Notify (%4.4s, %X) node %p\n", - acpi_ut_get_node_name(node), - notify_value, node)); - } - - notify_info->common.descriptor_type = - ACPI_DESC_TYPE_STATE_NOTIFY; - notify_info->notify.node = node; - notify_info->notify.value = (u16) notify_value; - notify_info->notify.handler_obj = handler_obj; - - status = - acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, - notify_info); - if (ACPI_FAILURE(status)) { - acpi_ut_delete_generic_state(notify_info); - } - } else { - /* There is no notify handler (per-device or system) for this device */ - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "No notify handler for Notify (%4.4s, %X) node %p\n", - acpi_ut_get_node_name(node), notify_value, - node)); - } - - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_notify_dispatch - * - * PARAMETERS: Context - To be passed to the notify handler - * - * RETURN: None. - * - * DESCRIPTION: Dispatch a device notification event to a previously - * installed handler. - * - ******************************************************************************/ - -static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) -{ - union acpi_generic_state *notify_info = - (union acpi_generic_state *)context; - acpi_notify_handler global_handler = NULL; - void *global_context = NULL; - union acpi_operand_object *handler_obj; - - ACPI_FUNCTION_ENTRY(); - - /* - * We will invoke a global notify handler if installed. This is done - * _before_ we invoke the per-device handler attached to the device. - */ - if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) { - - /* Global system notification handler */ - - if (acpi_gbl_system_notify.handler) { - global_handler = acpi_gbl_system_notify.handler; - global_context = acpi_gbl_system_notify.context; - } - } else { - /* Global driver notification handler */ - - if (acpi_gbl_device_notify.handler) { - global_handler = acpi_gbl_device_notify.handler; - global_context = acpi_gbl_device_notify.context; - } - } - - /* Invoke the system handler first, if present */ - - if (global_handler) { - global_handler(notify_info->notify.node, - notify_info->notify.value, global_context); - } - - /* Now invoke the per-device handler, if present */ - - handler_obj = notify_info->notify.handler_obj; - if (handler_obj) { - handler_obj->notify.handler(notify_info->notify.node, - notify_info->notify.value, - handler_obj->notify.context); - } - - /* All done with the info object */ - - acpi_ut_delete_generic_state(notify_info); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_global_lock_handler - * - * PARAMETERS: Context - From thread interface, not used - * - * RETURN: ACPI_INTERRUPT_HANDLED - * - * DESCRIPTION: Invoked directly from the SCI handler when a global lock - * release interrupt occurs. Attempt to acquire the global lock, - * if successful, signal the thread waiting for the lock. - * - * NOTE: Assumes that the semaphore can be signaled from interrupt level. If - * this is not possible for some reason, a separate thread will have to be - * scheduled to do this. - * - ******************************************************************************/ - -static u32 acpi_ev_global_lock_handler(void *context) -{ - u8 acquired = FALSE; - - /* - * Attempt to get the lock. - * - * If we don't get it now, it will be marked pending and we will - * take another interrupt when it becomes free. - */ - ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); - if (acquired) { - - /* Got the lock, now wake all threads waiting for it */ - - acpi_gbl_global_lock_acquired = TRUE; - /* Send a unit to the semaphore */ - - if (ACPI_FAILURE - (acpi_os_signal_semaphore - (acpi_gbl_global_lock_semaphore, 1))) { - ACPI_ERROR((AE_INFO, - "Could not signal Global Lock semaphore")); - } - } - - return (ACPI_INTERRUPT_HANDLED); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_init_global_lock_handler - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Install a handler for the global lock release event - * - ******************************************************************************/ - -acpi_status acpi_ev_init_global_lock_handler(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); - - /* Attempt installation of the global lock handler */ - - status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL, - acpi_ev_global_lock_handler, - NULL); - - /* - * If the global lock does not exist on this platform, the attempt to - * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick). - * Map to AE_OK, but mark global lock as not present. Any attempt to - * actually use the global lock will be flagged with an error. - */ - if (status == AE_NO_HARDWARE_RESPONSE) { - ACPI_ERROR((AE_INFO, - "No response from Global Lock hardware, disabling lock")); - - acpi_gbl_global_lock_present = FALSE; - return_ACPI_STATUS(AE_OK); - } - - acpi_gbl_global_lock_present = TRUE; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_remove_global_lock_handler - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Remove the handler for the Global Lock - * - ******************************************************************************/ - -static acpi_status acpi_ev_remove_global_lock_handler(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_remove_global_lock_handler); - - acpi_gbl_global_lock_present = FALSE; - status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL, - acpi_ev_global_lock_handler); - - return_ACPI_STATUS(status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_ev_acquire_global_lock - * - * PARAMETERS: Timeout - Max time to wait for the lock, in millisec. - * - * RETURN: Status - * - * DESCRIPTION: Attempt to gain ownership of the Global Lock. - * - * MUTEX: Interpreter must be locked - * - * Note: The original implementation allowed multiple threads to "acquire" the - * Global Lock, and the OS would hold the lock until the last thread had - * released it. However, this could potentially starve the BIOS out of the - * lock, especially in the case where there is a tight handshake between the - * Embedded Controller driver and the BIOS. Therefore, this implementation - * allows only one thread to acquire the HW Global Lock at a time, and makes - * the global lock appear as a standard mutex on the OS side. - * - *****************************************************************************/ -static acpi_thread_id acpi_ev_global_lock_thread_id; -static int acpi_ev_global_lock_acquired; - -acpi_status acpi_ev_acquire_global_lock(u16 timeout) -{ - acpi_status status = AE_OK; - u8 acquired = FALSE; - - ACPI_FUNCTION_TRACE(ev_acquire_global_lock); - - /* - * Only one thread can acquire the GL at a time, the global_lock_mutex - * enforces this. This interface releases the interpreter if we must wait. - */ - status = acpi_ex_system_wait_mutex( - acpi_gbl_global_lock_mutex->mutex.os_mutex, 0); - if (status == AE_TIME) { - if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { - acpi_ev_global_lock_acquired++; - return AE_OK; - } - } - - if (ACPI_FAILURE(status)) { - status = acpi_ex_system_wait_mutex( - acpi_gbl_global_lock_mutex->mutex.os_mutex, - timeout); - } - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - acpi_ev_global_lock_thread_id = acpi_os_get_thread_id(); - acpi_ev_global_lock_acquired++; - - /* - * Update the global lock handle and check for wraparound. The handle is - * only used for the external global lock interfaces, but it is updated - * here to properly handle the case where a single thread may acquire the - * lock via both the AML and the acpi_acquire_global_lock interfaces. The - * handle is therefore updated on the first acquire from a given thread - * regardless of where the acquisition request originated. - */ - acpi_gbl_global_lock_handle++; - if (acpi_gbl_global_lock_handle == 0) { - acpi_gbl_global_lock_handle = 1; - } - - /* - * Make sure that a global lock actually exists. If not, just treat the - * lock as a standard mutex. - */ - if (!acpi_gbl_global_lock_present) { - acpi_gbl_global_lock_acquired = TRUE; - return_ACPI_STATUS(AE_OK); - } - - /* Attempt to acquire the actual hardware lock */ - - ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); - if (acquired) { - - /* We got the lock */ - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Acquired hardware Global Lock\n")); - - acpi_gbl_global_lock_acquired = TRUE; - return_ACPI_STATUS(AE_OK); - } - - /* - * Did not get the lock. The pending bit was set above, and we must now - * wait until we get the global lock released interrupt. - */ - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n")); - - /* - * Wait for handshake with the global lock interrupt handler. - * This interface releases the interpreter if we must wait. - */ - status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, - ACPI_WAIT_FOREVER); - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_release_global_lock - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Releases ownership of the Global Lock. - * - ******************************************************************************/ - -acpi_status acpi_ev_release_global_lock(void) -{ - u8 pending = FALSE; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ev_release_global_lock); - - /* Lock must be already acquired */ - - if (!acpi_gbl_global_lock_acquired) { - ACPI_WARNING((AE_INFO, - "Cannot release the ACPI Global Lock, it has not been acquired")); - return_ACPI_STATUS(AE_NOT_ACQUIRED); - } - - acpi_ev_global_lock_acquired--; - if (acpi_ev_global_lock_acquired > 0) { - return AE_OK; - } - - if (acpi_gbl_global_lock_present) { - - /* Allow any thread to release the lock */ - - ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_FACS, pending); - - /* - * If the pending bit was set, we must write GBL_RLS to the control - * register - */ - if (pending) { - status = - acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE, - 1); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Released hardware Global Lock\n")); - } - - acpi_gbl_global_lock_acquired = FALSE; - - /* Release the local GL mutex */ - acpi_ev_global_lock_thread_id = NULL; - acpi_ev_global_lock_acquired = 0; - acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex); - return_ACPI_STATUS(status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_ev_terminate - * - * PARAMETERS: none - * - * RETURN: none - * - * DESCRIPTION: Disable events and free memory allocated for table storage. - * - ******************************************************************************/ - -void acpi_ev_terminate(void) -{ - u32 i; - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_terminate); - - if (acpi_gbl_events_initialized) { - /* - * Disable all event-related functionality. In all cases, on error, - * print a message but obviously we don't abort. - */ - - /* Disable all fixed events */ - - for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { - status = acpi_disable_event(i, 0); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not disable fixed event %d", - (u32) i)); - } - } - - /* Disable all GPEs in all GPE blocks */ - - status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); - - /* Remove SCI handler */ - - status = acpi_ev_remove_sci_handler(); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); - } - - status = acpi_ev_remove_global_lock_handler(); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not remove Global Lock handler")); - } - } - - /* Deallocate all handler objects installed within GPE info structs */ - - status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL); - - /* Return to original mode if necessary */ - - if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) { - status = acpi_disable(); - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, "AcpiDisable failed")); - } - } - return_VOID; -} diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c deleted file mode 100644 index 7346093f43ed..000000000000 --- a/drivers/acpi/events/evregion.c +++ /dev/null @@ -1,1070 +0,0 @@ -/****************************************************************************** - * - * Module Name: evregion - ACPI address_space (op_region) handler dispatch - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EVENTS -ACPI_MODULE_NAME("evregion") - -/* Local prototypes */ -static acpi_status -acpi_ev_reg_run(acpi_handle obj_handle, - u32 level, void *context, void **return_value); - -static acpi_status -acpi_ev_install_handler(acpi_handle obj_handle, - u32 level, void *context, void **return_value); - -/* These are the address spaces that will get default handlers */ - -#define ACPI_NUM_DEFAULT_SPACES 4 - -static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { - ACPI_ADR_SPACE_SYSTEM_MEMORY, - ACPI_ADR_SPACE_SYSTEM_IO, - ACPI_ADR_SPACE_PCI_CONFIG, - ACPI_ADR_SPACE_DATA_TABLE -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_region_handlers - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Installs the core subsystem default address space handlers. - * - ******************************************************************************/ - -acpi_status acpi_ev_install_region_handlers(void) -{ - acpi_status status; - u32 i; - - ACPI_FUNCTION_TRACE(ev_install_region_handlers); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * All address spaces (PCI Config, EC, SMBus) are scope dependent and - * registration must occur for a specific device. - * - * In the case of the system memory and IO address spaces there is - * currently no device associated with the address space. For these we - * use the root. - * - * We install the default PCI config space handler at the root so that - * this space is immediately available even though the we have not - * enumerated all the PCI Root Buses yet. This is to conform to the ACPI - * specification which states that the PCI config space must be always - * available -- even though we are nowhere near ready to find the PCI root - * buses at this point. - * - * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler - * has already been installed (via acpi_install_address_space_handler). - * Similar for AE_SAME_HANDLER. - */ - for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { - status = acpi_ev_install_space_handler(acpi_gbl_root_node, - acpi_gbl_default_address_spaces - [i], - ACPI_DEFAULT_HANDLER, - NULL, NULL); - switch (status) { - case AE_OK: - case AE_SAME_HANDLER: - case AE_ALREADY_EXISTS: - - /* These exceptions are all OK */ - - status = AE_OK; - break; - - default: - - goto unlock_and_exit; - } - } - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_initialize_op_regions - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Execute _REG methods for all Operation Regions that have - * an installed default region handler. - * - ******************************************************************************/ - -acpi_status acpi_ev_initialize_op_regions(void) -{ - acpi_status status; - u32 i; - - ACPI_FUNCTION_TRACE(ev_initialize_op_regions); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Run the _REG methods for op_regions in each default address space */ - - for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { - /* - * TBD: Make sure handler is the DEFAULT handler, otherwise - * _REG will have already been run. - */ - status = acpi_ev_execute_reg_methods(acpi_gbl_root_node, - acpi_gbl_default_address_spaces - [i]); - } - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_execute_reg_method - * - * PARAMETERS: region_obj - Region object - * Function - Passed to _REG: On (1) or Off (0) - * - * RETURN: Status - * - * DESCRIPTION: Execute _REG method for a region - * - ******************************************************************************/ - -acpi_status -acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) -{ - struct acpi_evaluate_info *info; - union acpi_operand_object *args[3]; - union acpi_operand_object *region_obj2; - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_execute_reg_method); - - region_obj2 = acpi_ns_get_secondary_object(region_obj); - if (!region_obj2) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - if (region_obj2->extra.method_REG == NULL) { - return_ACPI_STATUS(AE_OK); - } - - /* Allocate and initialize the evaluation information block */ - - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); - if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - info->prefix_node = region_obj2->extra.method_REG; - info->pathname = NULL; - info->parameters = args; - info->flags = ACPI_IGNORE_RETURN_VALUE; - - /* - * The _REG method has two arguments: - * - * Arg0 - Integer: - * Operation region space ID Same value as region_obj->Region.space_id - * - * Arg1 - Integer: - * connection status 1 for connecting the handler, 0 for disconnecting - * the handler (Passed as a parameter) - */ - args[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!args[0]) { - status = AE_NO_MEMORY; - goto cleanup1; - } - - args[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!args[1]) { - status = AE_NO_MEMORY; - goto cleanup2; - } - - /* Setup the parameter objects */ - - args[0]->integer.value = region_obj->region.space_id; - args[1]->integer.value = function; - args[2] = NULL; - - /* Execute the method, no return value */ - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_METHOD, info->prefix_node, NULL)); - - status = acpi_ns_evaluate(info); - acpi_ut_remove_reference(args[1]); - - cleanup2: - acpi_ut_remove_reference(args[0]); - - cleanup1: - ACPI_FREE(info); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_address_space_dispatch - * - * PARAMETERS: region_obj - Internal region object - * Function - Read or Write operation - * Address - Where in the space to read or write - * bit_width - Field width in bits (8, 16, 32, or 64) - * Value - Pointer to in or out value, must be - * full 64-bit acpi_integer - * - * RETURN: Status - * - * DESCRIPTION: Dispatch an address space or operation region access to - * a previously installed handler. - * - ******************************************************************************/ - -acpi_status -acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, - u32 function, - acpi_physical_address address, - u32 bit_width, acpi_integer * value) -{ - acpi_status status; - acpi_adr_space_handler handler; - acpi_adr_space_setup region_setup; - union acpi_operand_object *handler_desc; - union acpi_operand_object *region_obj2; - void *region_context = NULL; - - ACPI_FUNCTION_TRACE(ev_address_space_dispatch); - - region_obj2 = acpi_ns_get_secondary_object(region_obj); - if (!region_obj2) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* Ensure that there is a handler associated with this region */ - - handler_desc = region_obj->region.handler; - if (!handler_desc) { - ACPI_ERROR((AE_INFO, - "No handler for Region [%4.4s] (%p) [%s]", - acpi_ut_get_node_name(region_obj->region.node), - region_obj, - acpi_ut_get_region_name(region_obj->region. - space_id))); - - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* - * It may be the case that the region has never been initialized. - * Some types of regions require special init code - */ - if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { - - /* This region has not been initialized yet, do it */ - - region_setup = handler_desc->address_space.setup; - if (!region_setup) { - - /* No initialization routine, exit with error */ - - ACPI_ERROR((AE_INFO, - "No init routine for region(%p) [%s]", - region_obj, - acpi_ut_get_region_name(region_obj->region. - space_id))); - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* - * We must exit the interpreter because the region setup will - * potentially execute control methods (for example, the _REG method - * for this region) - */ - acpi_ex_exit_interpreter(); - - status = region_setup(region_obj, ACPI_REGION_ACTIVATE, - handler_desc->address_space.context, - ®ion_context); - - /* Re-enter the interpreter */ - - acpi_ex_enter_interpreter(); - - /* Check for failure of the Region Setup */ - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "During region initialization: [%s]", - acpi_ut_get_region_name(region_obj-> - region. - space_id))); - return_ACPI_STATUS(status); - } - - /* Region initialization may have been completed by region_setup */ - - if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { - region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; - - if (region_obj2->extra.region_context) { - - /* The handler for this region was already installed */ - - ACPI_FREE(region_context); - } else { - /* - * Save the returned context for use in all accesses to - * this particular region - */ - region_obj2->extra.region_context = - region_context; - } - } - } - - /* We have everything we need, we can invoke the address space handler */ - - handler = handler_desc->address_space.handler; - - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", - ®ion_obj->region.handler->address_space, handler, - ACPI_FORMAT_NATIVE_UINT(address), - acpi_ut_get_region_name(region_obj->region. - space_id))); - - if (!(handler_desc->address_space.handler_flags & - ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { - /* - * For handlers other than the default (supplied) handlers, we must - * exit the interpreter because the handler *might* block -- we don't - * know what it will do, so we can't hold the lock on the intepreter. - */ - acpi_ex_exit_interpreter(); - } - - /* Call the handler */ - - status = handler(function, address, bit_width, value, - handler_desc->address_space.context, - region_obj2->extra.region_context); - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]", - acpi_ut_get_region_name(region_obj->region. - space_id))); - } - - if (!(handler_desc->address_space.handler_flags & - ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { - /* - * We just returned from a non-default handler, we must re-enter the - * interpreter - */ - acpi_ex_enter_interpreter(); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_detach_region - * - * PARAMETERS: region_obj - Region Object - * acpi_ns_is_locked - Namespace Region Already Locked? - * - * RETURN: None - * - * DESCRIPTION: Break the association between the handler and the region - * this is a two way association. - * - ******************************************************************************/ - -void -acpi_ev_detach_region(union acpi_operand_object *region_obj, - u8 acpi_ns_is_locked) -{ - union acpi_operand_object *handler_obj; - union acpi_operand_object *obj_desc; - union acpi_operand_object **last_obj_ptr; - acpi_adr_space_setup region_setup; - void **region_context; - union acpi_operand_object *region_obj2; - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_detach_region); - - region_obj2 = acpi_ns_get_secondary_object(region_obj); - if (!region_obj2) { - return_VOID; - } - region_context = ®ion_obj2->extra.region_context; - - /* Get the address handler from the region object */ - - handler_obj = region_obj->region.handler; - if (!handler_obj) { - - /* This region has no handler, all done */ - - return_VOID; - } - - /* Find this region in the handler's list */ - - obj_desc = handler_obj->address_space.region_list; - last_obj_ptr = &handler_obj->address_space.region_list; - - while (obj_desc) { - - /* Is this the correct Region? */ - - if (obj_desc == region_obj) { - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Removing Region %p from address handler %p\n", - region_obj, handler_obj)); - - /* This is it, remove it from the handler's list */ - - *last_obj_ptr = obj_desc->region.next; - obj_desc->region.next = NULL; /* Must clear field */ - - if (acpi_ns_is_locked) { - status = - acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_VOID; - } - } - - /* Now stop region accesses by executing the _REG method */ - - status = acpi_ev_execute_reg_method(region_obj, 0); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "from region _REG, [%s]", - acpi_ut_get_region_name - (region_obj->region.space_id))); - } - - if (acpi_ns_is_locked) { - status = - acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_VOID; - } - } - - /* - * If the region has been activated, call the setup handler with - * the deactivate notification - */ - if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { - region_setup = handler_obj->address_space.setup; - status = - region_setup(region_obj, - ACPI_REGION_DEACTIVATE, - handler_obj->address_space. - context, region_context); - - /* Init routine may fail, Just ignore errors */ - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "from region handler - deactivate, [%s]", - acpi_ut_get_region_name - (region_obj->region. - space_id))); - } - - region_obj->region.flags &= - ~(AOPOBJ_SETUP_COMPLETE); - } - - /* - * Remove handler reference in the region - * - * NOTE: this doesn't mean that the region goes away, the region - * is just inaccessible as indicated to the _REG method - * - * If the region is on the handler's list, this must be the - * region's handler - */ - region_obj->region.handler = NULL; - acpi_ut_remove_reference(handler_obj); - - return_VOID; - } - - /* Walk the linked list of handlers */ - - last_obj_ptr = &obj_desc->region.next; - obj_desc = obj_desc->region.next; - } - - /* If we get here, the region was not in the handler's region list */ - - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Cannot remove region %p from address handler %p\n", - region_obj, handler_obj)); - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_attach_region - * - * PARAMETERS: handler_obj - Handler Object - * region_obj - Region Object - * acpi_ns_is_locked - Namespace Region Already Locked? - * - * RETURN: None - * - * DESCRIPTION: Create the association between the handler and the region - * this is a two way association. - * - ******************************************************************************/ - -acpi_status -acpi_ev_attach_region(union acpi_operand_object *handler_obj, - union acpi_operand_object *region_obj, - u8 acpi_ns_is_locked) -{ - - ACPI_FUNCTION_TRACE(ev_attach_region); - - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Adding Region [%4.4s] %p to address handler %p [%s]\n", - acpi_ut_get_node_name(region_obj->region.node), - region_obj, handler_obj, - acpi_ut_get_region_name(region_obj->region. - space_id))); - - /* Link this region to the front of the handler's list */ - - region_obj->region.next = handler_obj->address_space.region_list; - handler_obj->address_space.region_list = region_obj; - - /* Install the region's handler */ - - if (region_obj->region.handler) { - return_ACPI_STATUS(AE_ALREADY_EXISTS); - } - - region_obj->region.handler = handler_obj; - acpi_ut_add_reference(handler_obj); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_handler - * - * PARAMETERS: walk_namespace callback - * - * DESCRIPTION: This routine installs an address handler into objects that are - * of type Region or Device. - * - * If the Object is a Device, and the device has a handler of - * the same type then the search is terminated in that branch. - * - * This is because the existing handler is closer in proximity - * to any more regions than the one we are trying to install. - * - ******************************************************************************/ - -static acpi_status -acpi_ev_install_handler(acpi_handle obj_handle, - u32 level, void *context, void **return_value) -{ - union acpi_operand_object *handler_obj; - union acpi_operand_object *next_handler_obj; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_NAME(ev_install_handler); - - handler_obj = (union acpi_operand_object *)context; - - /* Parameter validation */ - - if (!handler_obj) { - return (AE_OK); - } - - /* Convert and validate the device handle */ - - node = acpi_ns_map_handle_to_node(obj_handle); - if (!node) { - return (AE_BAD_PARAMETER); - } - - /* - * We only care about regions and objects that are allowed to have - * address space handlers - */ - if ((node->type != ACPI_TYPE_DEVICE) && - (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { - return (AE_OK); - } - - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - - /* No object, just exit */ - - return (AE_OK); - } - - /* Devices are handled different than regions */ - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) { - - /* Check if this Device already has a handler for this address space */ - - next_handler_obj = obj_desc->device.handler; - while (next_handler_obj) { - - /* Found a handler, is it for the same address space? */ - - if (next_handler_obj->address_space.space_id == - handler_obj->address_space.space_id) { - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Found handler for region [%s] in device %p(%p) handler %p\n", - acpi_ut_get_region_name - (handler_obj->address_space. - space_id), obj_desc, - next_handler_obj, - handler_obj)); - - /* - * Since the object we found it on was a device, then it - * means that someone has already installed a handler for - * the branch of the namespace from this device on. Just - * bail out telling the walk routine to not traverse this - * branch. This preserves the scoping rule for handlers. - */ - return (AE_CTRL_DEPTH); - } - - /* Walk the linked list of handlers attached to this device */ - - next_handler_obj = next_handler_obj->address_space.next; - } - - /* - * As long as the device didn't have a handler for this space we - * don't care about it. We just ignore it and proceed. - */ - return (AE_OK); - } - - /* Object is a Region */ - - if (obj_desc->region.space_id != handler_obj->address_space.space_id) { - - /* This region is for a different address space, just ignore it */ - - return (AE_OK); - } - - /* - * Now we have a region and it is for the handler's address space type. - * - * First disconnect region for any previous handler (if any) - */ - acpi_ev_detach_region(obj_desc, FALSE); - - /* Connect the region to the new handler */ - - status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE); - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_space_handler - * - * PARAMETERS: Node - Namespace node for the device - * space_id - The address space ID - * Handler - Address of the handler - * Setup - Address of the setup function - * Context - Value passed to the handler on each access - * - * RETURN: Status - * - * DESCRIPTION: Install a handler for all op_regions of a given space_id. - * Assumes namespace is locked - * - ******************************************************************************/ - -acpi_status -acpi_ev_install_space_handler(struct acpi_namespace_node * node, - acpi_adr_space_type space_id, - acpi_adr_space_handler handler, - acpi_adr_space_setup setup, void *context) -{ - union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj; - acpi_status status; - acpi_object_type type; - u8 flags = 0; - - ACPI_FUNCTION_TRACE(ev_install_space_handler); - - /* - * This registration is valid for only the types below and the root. This - * is where the default handlers get placed. - */ - if ((node->type != ACPI_TYPE_DEVICE) && - (node->type != ACPI_TYPE_PROCESSOR) && - (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - if (handler == ACPI_DEFAULT_HANDLER) { - flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; - - switch (space_id) { - case ACPI_ADR_SPACE_SYSTEM_MEMORY: - handler = acpi_ex_system_memory_space_handler; - setup = acpi_ev_system_memory_region_setup; - break; - - case ACPI_ADR_SPACE_SYSTEM_IO: - handler = acpi_ex_system_io_space_handler; - setup = acpi_ev_io_space_region_setup; - break; - - case ACPI_ADR_SPACE_PCI_CONFIG: - handler = acpi_ex_pci_config_space_handler; - setup = acpi_ev_pci_config_region_setup; - break; - - case ACPI_ADR_SPACE_CMOS: - handler = acpi_ex_cmos_space_handler; - setup = acpi_ev_cmos_region_setup; - break; - - case ACPI_ADR_SPACE_PCI_BAR_TARGET: - handler = acpi_ex_pci_bar_space_handler; - setup = acpi_ev_pci_bar_region_setup; - break; - - case ACPI_ADR_SPACE_DATA_TABLE: - handler = acpi_ex_data_table_space_handler; - setup = NULL; - break; - - default: - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - } - - /* If the caller hasn't specified a setup routine, use the default */ - - if (!setup) { - setup = acpi_ev_default_region_setup; - } - - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - /* - * The attached device object already exists. Make sure the handler - * is not already installed. - */ - handler_obj = obj_desc->device.handler; - - /* Walk the handler list for this device */ - - while (handler_obj) { - - /* Same space_id indicates a handler already installed */ - - if (handler_obj->address_space.space_id == space_id) { - if (handler_obj->address_space.handler == - handler) { - /* - * It is (relatively) OK to attempt to install the SAME - * handler twice. This can easily happen with the - * PCI_Config space. - */ - status = AE_SAME_HANDLER; - goto unlock_and_exit; - } else { - /* A handler is already installed */ - - status = AE_ALREADY_EXISTS; - } - goto unlock_and_exit; - } - - /* Walk the linked list of handlers */ - - handler_obj = handler_obj->address_space.next; - } - } else { - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Creating object on Device %p while installing handler\n", - node)); - - /* obj_desc does not exist, create one */ - - if (node->type == ACPI_TYPE_ANY) { - type = ACPI_TYPE_DEVICE; - } else { - type = node->type; - } - - obj_desc = acpi_ut_create_internal_object(type); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - /* Init new descriptor */ - - obj_desc->common.type = (u8) type; - - /* Attach the new object to the Node */ - - status = acpi_ns_attach_object(node, obj_desc, type); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - } - - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", - acpi_ut_get_region_name(space_id), space_id, - acpi_ut_get_node_name(node), node, obj_desc)); - - /* - * Install the handler - * - * At this point there is no existing handler. Just allocate the object - * for the handler and link it into the list. - */ - handler_obj = - acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER); - if (!handler_obj) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - /* Init handler obj */ - - handler_obj->address_space.space_id = (u8) space_id; - handler_obj->address_space.handler_flags = flags; - handler_obj->address_space.region_list = NULL; - handler_obj->address_space.node = node; - handler_obj->address_space.handler = handler; - handler_obj->address_space.context = context; - handler_obj->address_space.setup = setup; - - /* Install at head of Device.address_space list */ - - handler_obj->address_space.next = obj_desc->device.handler; - - /* - * The Device object is the first reference on the handler_obj. - * Each region that uses the handler adds a reference. - */ - obj_desc->device.handler = handler_obj; - - /* - * Walk the namespace finding all of the regions this - * handler will manage. - * - * Start at the device and search the branch toward - * the leaf nodes until either the leaf is encountered or - * a device is detected that has an address handler of the - * same type. - * - * In either case, back up and search down the remainder - * of the branch - */ - status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, - ACPI_NS_WALK_UNLOCK, - acpi_ev_install_handler, handler_obj, - NULL); - - unlock_and_exit: - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_execute_reg_methods - * - * PARAMETERS: Node - Namespace node for the device - * space_id - The address space ID - * - * RETURN: Status - * - * DESCRIPTION: Run all _REG methods for the input Space ID; - * Note: assumes namespace is locked, or system init time. - * - ******************************************************************************/ - -acpi_status -acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, - acpi_adr_space_type space_id) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_execute_reg_methods); - - /* - * Run all _REG methods for all Operation Regions for this space ID. This - * is a separate walk in order to handle any interdependencies between - * regions and _REG methods. (i.e. handlers must be installed for all - * regions of this Space ID before we can run any _REG methods) - */ - status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, - ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, - &space_id, NULL); - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_reg_run - * - * PARAMETERS: walk_namespace callback - * - * DESCRIPTION: Run _REG method for region objects of the requested space_iD - * - ******************************************************************************/ - -static acpi_status -acpi_ev_reg_run(acpi_handle obj_handle, - u32 level, void *context, void **return_value) -{ - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - acpi_adr_space_type space_id; - acpi_status status; - - space_id = *ACPI_CAST_PTR(acpi_adr_space_type, context); - - /* Convert and validate the device handle */ - - node = acpi_ns_map_handle_to_node(obj_handle); - if (!node) { - return (AE_BAD_PARAMETER); - } - - /* - * We only care about regions.and objects that are allowed to have address - * space handlers - */ - if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { - return (AE_OK); - } - - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - - /* No object, just exit */ - - return (AE_OK); - } - - /* Object is a Region */ - - if (obj_desc->region.space_id != space_id) { - - /* This region is for a different address space, just ignore it */ - - return (AE_OK); - } - - status = acpi_ev_execute_reg_method(obj_desc, 1); - return (status); -} diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c deleted file mode 100644 index 1b7f9fdbef15..000000000000 --- a/drivers/acpi/events/evrgnini.c +++ /dev/null @@ -1,684 +0,0 @@ -/****************************************************************************** - * - * Module Name: evrgnini- ACPI address_space (op_region) init - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_EVENTS -ACPI_MODULE_NAME("evrgnini") - -/* Local prototypes */ -static u8 acpi_ev_match_pci_root_bridge(char *id); - -static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); - -/******************************************************************************* - * - * FUNCTION: acpi_ev_system_memory_region_setup - * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop - * handler_context - Address space handler context - * region_context - Region specific context - * - * RETURN: Status - * - * DESCRIPTION: Setup a system_memory operation region - * - ******************************************************************************/ - -acpi_status -acpi_ev_system_memory_region_setup(acpi_handle handle, - u32 function, - void *handler_context, void **region_context) -{ - union acpi_operand_object *region_desc = - (union acpi_operand_object *)handle; - struct acpi_mem_space_context *local_region_context; - - ACPI_FUNCTION_TRACE(ev_system_memory_region_setup); - - if (function == ACPI_REGION_DEACTIVATE) { - if (*region_context) { - local_region_context = - (struct acpi_mem_space_context *)*region_context; - - /* Delete a cached mapping if present */ - - if (local_region_context->mapped_length) { - acpi_os_unmap_memory(local_region_context-> - mapped_logical_address, - local_region_context-> - mapped_length); - } - ACPI_FREE(local_region_context); - *region_context = NULL; - } - return_ACPI_STATUS(AE_OK); - } - - /* Create a new context */ - - local_region_context = - ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); - if (!(local_region_context)) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Save the region length and address for use in the handler */ - - local_region_context->length = region_desc->region.length; - local_region_context->address = region_desc->region.address; - - *region_context = local_region_context; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_io_space_region_setup - * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop - * handler_context - Address space handler context - * region_context - Region specific context - * - * RETURN: Status - * - * DESCRIPTION: Setup a IO operation region - * - ******************************************************************************/ - -acpi_status -acpi_ev_io_space_region_setup(acpi_handle handle, - u32 function, - void *handler_context, void **region_context) -{ - ACPI_FUNCTION_TRACE(ev_io_space_region_setup); - - if (function == ACPI_REGION_DEACTIVATE) { - *region_context = NULL; - } else { - *region_context = handler_context; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_pci_config_region_setup - * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop - * handler_context - Address space handler context - * region_context - Region specific context - * - * RETURN: Status - * - * DESCRIPTION: Setup a PCI_Config operation region - * - * MUTEX: Assumes namespace is not locked - * - ******************************************************************************/ - -acpi_status -acpi_ev_pci_config_region_setup(acpi_handle handle, - u32 function, - void *handler_context, void **region_context) -{ - acpi_status status = AE_OK; - acpi_integer pci_value; - struct acpi_pci_id *pci_id = *region_context; - union acpi_operand_object *handler_obj; - struct acpi_namespace_node *parent_node; - struct acpi_namespace_node *pci_root_node; - struct acpi_namespace_node *pci_device_node; - union acpi_operand_object *region_obj = - (union acpi_operand_object *)handle; - - ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); - - handler_obj = region_obj->region.handler; - if (!handler_obj) { - /* - * No installed handler. This shouldn't happen because the dispatch - * routine checks before we get here, but we check again just in case. - */ - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Attempting to init a region %p, with no handler\n", - region_obj)); - return_ACPI_STATUS(AE_NOT_EXIST); - } - - *region_context = NULL; - if (function == ACPI_REGION_DEACTIVATE) { - if (pci_id) { - ACPI_FREE(pci_id); - } - return_ACPI_STATUS(status); - } - - parent_node = acpi_ns_get_parent_node(region_obj->region.node); - - /* - * Get the _SEG and _BBN values from the device upon which the handler - * is installed. - * - * We need to get the _SEG and _BBN objects relative to the PCI BUS device. - * This is the device the handler has been registered to handle. - */ - - /* - * If the address_space.Node is still pointing to the root, we need - * to scan upward for a PCI Root bridge and re-associate the op_region - * handlers with that device. - */ - if (handler_obj->address_space.node == acpi_gbl_root_node) { - - /* Start search from the parent object */ - - pci_root_node = parent_node; - while (pci_root_node != acpi_gbl_root_node) { - - /* Get the _HID/_CID in order to detect a root_bridge */ - - if (acpi_ev_is_pci_root_bridge(pci_root_node)) { - - /* Install a handler for this PCI root bridge */ - - status = - acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); - if (ACPI_FAILURE(status)) { - if (status == AE_SAME_HANDLER) { - /* - * It is OK if the handler is already installed on the - * root bridge. Still need to return a context object - * for the new PCI_Config operation region, however. - */ - status = AE_OK; - } else { - ACPI_EXCEPTION((AE_INFO, status, - "Could not install PciConfig handler for Root Bridge %4.4s", - acpi_ut_get_node_name - (pci_root_node))); - } - } - break; - } - - pci_root_node = acpi_ns_get_parent_node(pci_root_node); - } - - /* PCI root bridge not found, use namespace root node */ - } else { - pci_root_node = handler_obj->address_space.node; - } - - /* - * If this region is now initialized, we are done. - * (install_address_space_handler could have initialized it) - */ - if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { - return_ACPI_STATUS(AE_OK); - } - - /* Region is still not initialized. Create a new context */ - - pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id)); - if (!pci_id) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* - * For PCI_Config space access, we need the segment, bus, device and - * function numbers. Acquire them here. - * - * Find the parent device object. (This allows the operation region to be - * within a subscope under the device, such as a control method.) - */ - pci_device_node = region_obj->region.node; - while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) { - pci_device_node = acpi_ns_get_parent_node(pci_device_node); - } - - if (!pci_device_node) { - ACPI_FREE(pci_id); - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* - * Get the PCI device and function numbers from the _ADR object contained - * in the parent's scope. - */ - status = - acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, pci_device_node, - &pci_value); - - /* - * The default is zero, and since the allocation above zeroed the data, - * just do nothing on failure. - */ - if (ACPI_SUCCESS(status)) { - pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value)); - pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value)); - } - - /* The PCI segment number comes from the _SEG method */ - - status = - acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, pci_root_node, - &pci_value); - if (ACPI_SUCCESS(status)) { - pci_id->segment = ACPI_LOWORD(pci_value); - } - - /* The PCI bus number comes from the _BBN method */ - - status = - acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, pci_root_node, - &pci_value); - if (ACPI_SUCCESS(status)) { - pci_id->bus = ACPI_LOWORD(pci_value); - } - - /* Complete this device's pci_id */ - - acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id); - - *region_context = pci_id; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_match_pci_root_bridge - * - * PARAMETERS: Id - The HID/CID in string format - * - * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge - * - * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. - * - ******************************************************************************/ - -static u8 acpi_ev_match_pci_root_bridge(char *id) -{ - - /* - * Check if this is a PCI root. - * ACPI 3.0+: check for a PCI Express root also. - */ - if (!(ACPI_STRNCMP(id, - PCI_ROOT_HID_STRING, - sizeof(PCI_ROOT_HID_STRING))) || - !(ACPI_STRNCMP(id, - PCI_EXPRESS_ROOT_HID_STRING, - sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) { - return (TRUE); - } - - return (FALSE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_is_pci_root_bridge - * - * PARAMETERS: Node - Device node being examined - * - * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge - * - * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by - * examining the _HID and _CID for the device. - * - ******************************************************************************/ - -static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) -{ - acpi_status status; - struct acpica_device_id hid; - struct acpi_compatible_id_list *cid; - u32 i; - - /* Get the _HID and check for a PCI Root Bridge */ - - status = acpi_ut_execute_HID(node, &hid); - if (ACPI_FAILURE(status)) { - return (FALSE); - } - - if (acpi_ev_match_pci_root_bridge(hid.value)) { - return (TRUE); - } - - /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */ - - status = acpi_ut_execute_CID(node, &cid); - if (ACPI_FAILURE(status)) { - return (FALSE); - } - - /* Check all _CIDs in the returned list */ - - for (i = 0; i < cid->count; i++) { - if (acpi_ev_match_pci_root_bridge(cid->id[i].value)) { - ACPI_FREE(cid); - return (TRUE); - } - } - - ACPI_FREE(cid); - return (FALSE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_pci_bar_region_setup - * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop - * handler_context - Address space handler context - * region_context - Region specific context - * - * RETURN: Status - * - * DESCRIPTION: Setup a pci_bAR operation region - * - * MUTEX: Assumes namespace is not locked - * - ******************************************************************************/ - -acpi_status -acpi_ev_pci_bar_region_setup(acpi_handle handle, - u32 function, - void *handler_context, void **region_context) -{ - ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_cmos_region_setup - * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop - * handler_context - Address space handler context - * region_context - Region specific context - * - * RETURN: Status - * - * DESCRIPTION: Setup a CMOS operation region - * - * MUTEX: Assumes namespace is not locked - * - ******************************************************************************/ - -acpi_status -acpi_ev_cmos_region_setup(acpi_handle handle, - u32 function, - void *handler_context, void **region_context) -{ - ACPI_FUNCTION_TRACE(ev_cmos_region_setup); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_default_region_setup - * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop - * handler_context - Address space handler context - * region_context - Region specific context - * - * RETURN: Status - * - * DESCRIPTION: Default region initialization - * - ******************************************************************************/ - -acpi_status -acpi_ev_default_region_setup(acpi_handle handle, - u32 function, - void *handler_context, void **region_context) -{ - ACPI_FUNCTION_TRACE(ev_default_region_setup); - - if (function == ACPI_REGION_DEACTIVATE) { - *region_context = NULL; - } else { - *region_context = handler_context; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_initialize_region - * - * PARAMETERS: region_obj - Region we are initializing - * acpi_ns_locked - Is namespace locked? - * - * RETURN: Status - * - * DESCRIPTION: Initializes the region, finds any _REG methods and saves them - * for execution at a later time - * - * Get the appropriate address space handler for a newly - * created region. - * - * This also performs address space specific initialization. For - * example, PCI regions must have an _ADR object that contains - * a PCI address in the scope of the definition. This address is - * required to perform an access to PCI config space. - * - * MUTEX: Interpreter should be unlocked, because we may run the _REG - * method for this region. - * - ******************************************************************************/ - -acpi_status -acpi_ev_initialize_region(union acpi_operand_object *region_obj, - u8 acpi_ns_locked) -{ - union acpi_operand_object *handler_obj; - union acpi_operand_object *obj_desc; - acpi_adr_space_type space_id; - struct acpi_namespace_node *node; - acpi_status status; - struct acpi_namespace_node *method_node; - acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG; - union acpi_operand_object *region_obj2; - - ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked); - - if (!region_obj) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) { - return_ACPI_STATUS(AE_OK); - } - - region_obj2 = acpi_ns_get_secondary_object(region_obj); - if (!region_obj2) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - node = acpi_ns_get_parent_node(region_obj->region.node); - space_id = region_obj->region.space_id; - - /* Setup defaults */ - - region_obj->region.handler = NULL; - region_obj2->extra.method_REG = NULL; - region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE); - region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; - - /* Find any "_REG" method associated with this region definition */ - - status = - acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD, - &method_node); - if (ACPI_SUCCESS(status)) { - /* - * The _REG method is optional and there can be only one per region - * definition. This will be executed when the handler is attached - * or removed - */ - region_obj2->extra.method_REG = method_node; - } - - /* - * The following loop depends upon the root Node having no parent - * ie: acpi_gbl_root_node->parent_entry being set to NULL - */ - while (node) { - - /* Check to see if a handler exists */ - - handler_obj = NULL; - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - - /* Can only be a handler if the object exists */ - - switch (node->type) { - case ACPI_TYPE_DEVICE: - - handler_obj = obj_desc->device.handler; - break; - - case ACPI_TYPE_PROCESSOR: - - handler_obj = obj_desc->processor.handler; - break; - - case ACPI_TYPE_THERMAL: - - handler_obj = obj_desc->thermal_zone.handler; - break; - - default: - /* Ignore other objects */ - break; - } - - while (handler_obj) { - - /* Is this handler of the correct type? */ - - if (handler_obj->address_space.space_id == - space_id) { - - /* Found correct handler */ - - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Found handler %p for region %p in obj %p\n", - handler_obj, - region_obj, - obj_desc)); - - status = - acpi_ev_attach_region(handler_obj, - region_obj, - acpi_ns_locked); - - /* - * Tell all users that this region is usable by running the _REG - * method - */ - if (acpi_ns_locked) { - status = - acpi_ut_release_mutex - (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS - (status); - } - } - - status = - acpi_ev_execute_reg_method - (region_obj, 1); - - if (acpi_ns_locked) { - status = - acpi_ut_acquire_mutex - (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS - (status); - } - } - - return_ACPI_STATUS(AE_OK); - } - - /* Try next handler in the list */ - - handler_obj = handler_obj->address_space.next; - } - } - - /* This node does not have the handler we need; Pop up one level */ - - node = acpi_ns_get_parent_node(node); - } - - /* If we get here, there is no handler for this region */ - - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "No handler for RegionType %s(%X) (RegionObj %p)\n", - acpi_ut_get_region_name(space_id), space_id, - region_obj)); - - return_ACPI_STATUS(AE_NOT_EXIST); -} diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c deleted file mode 100644 index 18dce10c5fb1..000000000000 --- a/drivers/acpi/events/evsci.c +++ /dev/null @@ -1,183 +0,0 @@ -/******************************************************************************* - * - * Module Name: evsci - System Control Interrupt configuration and - * legacy to ACPI mode state transition functions - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_EVENTS -ACPI_MODULE_NAME("evsci") - -/* Local prototypes */ -static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context); - -/******************************************************************************* - * - * FUNCTION: acpi_ev_sci_xrupt_handler - * - * PARAMETERS: Context - Calling Context - * - * RETURN: Status code indicates whether interrupt was handled. - * - * DESCRIPTION: Interrupt handler that will figure out what function or - * control method to call to deal with a SCI. - * - ******************************************************************************/ - -static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) -{ - struct acpi_gpe_xrupt_info *gpe_xrupt_list = context; - u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; - - ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler); - - /* - * We are guaranteed by the ACPI CA initialization/shutdown code that - * if this interrupt handler is installed, ACPI is enabled. - */ - - /* - * Fixed Events: - * Check for and dispatch any Fixed Events that have occurred - */ - interrupt_handled |= acpi_ev_fixed_event_detect(); - - /* - * General Purpose Events: - * Check for and dispatch any GPEs that have occurred - */ - interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - - return_UINT32(interrupt_handled); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_gpe_xrupt_handler - * - * PARAMETERS: Context - Calling Context - * - * RETURN: Status code indicates whether interrupt was handled. - * - * DESCRIPTION: Handler for GPE Block Device interrupts - * - ******************************************************************************/ - -u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context) -{ - struct acpi_gpe_xrupt_info *gpe_xrupt_list = context; - u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; - - ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler); - - /* - * We are guaranteed by the ACPI CA initialization/shutdown code that - * if this interrupt handler is installed, ACPI is enabled. - */ - - /* GPEs: Check for and dispatch any GPEs that have occurred */ - - interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - - return_UINT32(interrupt_handled); -} - -/****************************************************************************** - * - * FUNCTION: acpi_ev_install_sci_handler - * - * PARAMETERS: none - * - * RETURN: Status - * - * DESCRIPTION: Installs SCI handler. - * - ******************************************************************************/ - -u32 acpi_ev_install_sci_handler(void) -{ - u32 status = AE_OK; - - ACPI_FUNCTION_TRACE(ev_install_sci_handler); - - status = - acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, - acpi_ev_sci_xrupt_handler, - acpi_gbl_gpe_xrupt_list_head); - return_ACPI_STATUS(status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_ev_remove_sci_handler - * - * PARAMETERS: none - * - * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not - * installed to begin with - * - * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be - * taken. - * - * Note: It doesn't seem important to disable all events or set the event - * enable registers to their original values. The OS should disable - * the SCI interrupt level when the handler is removed, so no more - * events will come in. - * - ******************************************************************************/ - -acpi_status acpi_ev_remove_sci_handler(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_remove_sci_handler); - - /* Just let the OS remove the handler and disable the level */ - - status = - acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, - acpi_ev_sci_xrupt_handler); - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c deleted file mode 100644 index 3b6a069f5b06..000000000000 --- a/drivers/acpi/events/evxface.c +++ /dev/null @@ -1,821 +0,0 @@ -/****************************************************************************** - * - * Module Name: evxface - External interfaces for ACPI events - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EVENTS -ACPI_MODULE_NAME("evxface") - -/******************************************************************************* - * - * FUNCTION: acpi_install_exception_handler - * - * PARAMETERS: Handler - Pointer to the handler function for the - * event - * - * RETURN: Status - * - * DESCRIPTION: Saves the pointer to the handler function - * - ******************************************************************************/ -#ifdef ACPI_FUTURE_USAGE -acpi_status acpi_install_exception_handler(acpi_exception_handler handler) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_install_exception_handler); - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Don't allow two handlers. */ - - if (acpi_gbl_exception_handler) { - status = AE_ALREADY_EXISTS; - goto cleanup; - } - - /* Install the handler */ - - acpi_gbl_exception_handler = handler; - - cleanup: - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) -#endif /* ACPI_FUTURE_USAGE */ -/******************************************************************************* - * - * FUNCTION: acpi_install_fixed_event_handler - * - * PARAMETERS: Event - Event type to enable. - * Handler - Pointer to the handler function for the - * event - * Context - Value passed to the handler on each GPE - * - * RETURN: Status - * - * DESCRIPTION: Saves the pointer to the handler function and then enables the - * event. - * - ******************************************************************************/ -acpi_status -acpi_install_fixed_event_handler(u32 event, - acpi_event_handler handler, void *context) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler); - - /* Parameter validation */ - - if (event > ACPI_EVENT_MAX) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Don't allow two handlers. */ - - if (NULL != acpi_gbl_fixed_event_handlers[event].handler) { - status = AE_ALREADY_EXISTS; - goto cleanup; - } - - /* Install the handler before enabling the event */ - - acpi_gbl_fixed_event_handlers[event].handler = handler; - acpi_gbl_fixed_event_handlers[event].context = context; - - status = acpi_clear_event(event); - if (ACPI_SUCCESS(status)) - status = acpi_enable_event(event, 0); - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, "Could not enable fixed event %X", - event)); - - /* Remove the handler */ - - acpi_gbl_fixed_event_handlers[event].handler = NULL; - acpi_gbl_fixed_event_handlers[event].context = NULL; - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Enabled fixed event %X, Handler=%p\n", event, - handler)); - } - - cleanup: - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler) - -/******************************************************************************* - * - * FUNCTION: acpi_remove_fixed_event_handler - * - * PARAMETERS: Event - Event type to disable. - * Handler - Address of the handler - * - * RETURN: Status - * - * DESCRIPTION: Disables the event and unregisters the event handler. - * - ******************************************************************************/ -acpi_status -acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler); - - /* Parameter validation */ - - if (event > ACPI_EVENT_MAX) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Disable the event before removing the handler */ - - status = acpi_disable_event(event, 0); - - /* Always Remove the handler */ - - acpi_gbl_fixed_event_handlers[event].handler = NULL; - acpi_gbl_fixed_event_handlers[event].context = NULL; - - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, - "Could not write to fixed event enable register %X", - event)); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n", - event)); - } - - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler) - -/******************************************************************************* - * - * FUNCTION: acpi_install_notify_handler - * - * PARAMETERS: Device - The device for which notifies will be handled - * handler_type - The type of handler: - * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) - * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) - * ACPI_ALL_NOTIFY: both system and device - * Handler - Address of the handler - * Context - Value passed to the handler on each GPE - * - * RETURN: Status - * - * DESCRIPTION: Install a handler for notifies on an ACPI device - * - ******************************************************************************/ -acpi_status -acpi_install_notify_handler(acpi_handle device, - u32 handler_type, - acpi_notify_handler handler, void *context) -{ - union acpi_operand_object *obj_desc; - union acpi_operand_object *notify_obj; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_install_notify_handler); - - /* Parameter validation */ - - if ((!device) || - (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Convert and validate the device handle */ - - node = acpi_ns_map_handle_to_node(device); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* - * Root Object: - * Registering a notify handler on the root object indicates that the - * caller wishes to receive notifications for all objects. Note that - * only one global handler can be regsitered (per notify type). - */ - if (device == ACPI_ROOT_OBJECT) { - - /* Make sure the handler is not already installed */ - - if (((handler_type & ACPI_SYSTEM_NOTIFY) && - acpi_gbl_system_notify.handler) || - ((handler_type & ACPI_DEVICE_NOTIFY) && - acpi_gbl_device_notify.handler)) { - status = AE_ALREADY_EXISTS; - goto unlock_and_exit; - } - - if (handler_type & ACPI_SYSTEM_NOTIFY) { - acpi_gbl_system_notify.node = node; - acpi_gbl_system_notify.handler = handler; - acpi_gbl_system_notify.context = context; - } - - if (handler_type & ACPI_DEVICE_NOTIFY) { - acpi_gbl_device_notify.node = node; - acpi_gbl_device_notify.handler = handler; - acpi_gbl_device_notify.context = context; - } - - /* Global notify handler installed */ - } - - /* - * All Other Objects: - * Caller will only receive notifications specific to the target object. - * Note that only certain object types can receive notifications. - */ - else { - /* Notifies allowed on this object? */ - - if (!acpi_ev_is_notify_object(node)) { - status = AE_TYPE; - goto unlock_and_exit; - } - - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - - /* Object exists - make sure there's no handler */ - - if (((handler_type & ACPI_SYSTEM_NOTIFY) && - obj_desc->common_notify.system_notify) || - ((handler_type & ACPI_DEVICE_NOTIFY) && - obj_desc->common_notify.device_notify)) { - status = AE_ALREADY_EXISTS; - goto unlock_and_exit; - } - } else { - /* Create a new object */ - - obj_desc = acpi_ut_create_internal_object(node->type); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - /* Attach new object to the Node */ - - status = - acpi_ns_attach_object(device, obj_desc, node->type); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - } - - /* Install the handler */ - - notify_obj = - acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); - if (!notify_obj) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - notify_obj->notify.node = node; - notify_obj->notify.handler = handler; - notify_obj->notify.context = context; - - if (handler_type & ACPI_SYSTEM_NOTIFY) { - obj_desc->common_notify.system_notify = notify_obj; - } - - if (handler_type & ACPI_DEVICE_NOTIFY) { - obj_desc->common_notify.device_notify = notify_obj; - } - - if (handler_type == ACPI_ALL_NOTIFY) { - - /* Extra ref if installed in both */ - - acpi_ut_add_reference(notify_obj); - } - } - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) - -/******************************************************************************* - * - * FUNCTION: acpi_remove_notify_handler - * - * PARAMETERS: Device - The device for which notifies will be handled - * handler_type - The type of handler: - * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) - * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) - * ACPI_ALL_NOTIFY: both system and device - * Handler - Address of the handler - * - * RETURN: Status - * - * DESCRIPTION: Remove a handler for notifies on an ACPI device - * - ******************************************************************************/ -acpi_status -acpi_remove_notify_handler(acpi_handle device, - u32 handler_type, acpi_notify_handler handler) -{ - union acpi_operand_object *notify_obj; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); - - /* Parameter validation */ - - if ((!device) || - (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { - status = AE_BAD_PARAMETER; - goto exit; - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* Convert and validate the device handle */ - - node = acpi_ns_map_handle_to_node(device); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Root Object */ - - if (device == ACPI_ROOT_OBJECT) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Removing notify handler for namespace root object\n")); - - if (((handler_type & ACPI_SYSTEM_NOTIFY) && - !acpi_gbl_system_notify.handler) || - ((handler_type & ACPI_DEVICE_NOTIFY) && - !acpi_gbl_device_notify.handler)) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } - - /* Make sure all deferred tasks are completed */ - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - acpi_os_wait_events_complete(NULL); - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto exit; - } - - if (handler_type & ACPI_SYSTEM_NOTIFY) { - acpi_gbl_system_notify.node = NULL; - acpi_gbl_system_notify.handler = NULL; - acpi_gbl_system_notify.context = NULL; - } - - if (handler_type & ACPI_DEVICE_NOTIFY) { - acpi_gbl_device_notify.node = NULL; - acpi_gbl_device_notify.handler = NULL; - acpi_gbl_device_notify.context = NULL; - } - } - - /* All Other Objects */ - - else { - /* Notifies allowed on this object? */ - - if (!acpi_ev_is_notify_object(node)) { - status = AE_TYPE; - goto unlock_and_exit; - } - - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } - - /* Object exists - make sure there's an existing handler */ - - if (handler_type & ACPI_SYSTEM_NOTIFY) { - notify_obj = obj_desc->common_notify.system_notify; - if (!notify_obj) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } - - if (notify_obj->notify.handler != handler) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - /* Make sure all deferred tasks are completed */ - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - acpi_os_wait_events_complete(NULL); - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* Remove the handler */ - obj_desc->common_notify.system_notify = NULL; - acpi_ut_remove_reference(notify_obj); - } - - if (handler_type & ACPI_DEVICE_NOTIFY) { - notify_obj = obj_desc->common_notify.device_notify; - if (!notify_obj) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } - - if (notify_obj->notify.handler != handler) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - /* Make sure all deferred tasks are completed */ - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - acpi_os_wait_events_complete(NULL); - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* Remove the handler */ - obj_desc->common_notify.device_notify = NULL; - acpi_ut_remove_reference(notify_obj); - } - } - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - exit: - if (ACPI_FAILURE(status)) - ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler")); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) - -/******************************************************************************* - * - * FUNCTION: acpi_install_gpe_handler - * - * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT - * defined GPEs) - * gpe_number - The GPE number within the GPE block - * Type - Whether this GPE should be treated as an - * edge- or level-triggered interrupt. - * Address - Address of the handler - * Context - Value passed to the handler on each GPE - * - * RETURN: Status - * - * DESCRIPTION: Install a handler for a General Purpose Event. - * - ******************************************************************************/ -acpi_status -acpi_install_gpe_handler(acpi_handle gpe_device, - u32 gpe_number, - u32 type, acpi_event_handler address, void *context) -{ - struct acpi_gpe_event_info *gpe_event_info; - struct acpi_handler_info *handler; - acpi_status status; - acpi_cpu_flags flags; - - ACPI_FUNCTION_TRACE(acpi_install_gpe_handler); - - /* Parameter validation */ - - if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) { - status = AE_BAD_PARAMETER; - goto exit; - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* Ensure that we have a valid GPE number */ - - gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); - if (!gpe_event_info) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Make sure that there isn't a handler there already */ - - if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == - ACPI_GPE_DISPATCH_HANDLER) { - status = AE_ALREADY_EXISTS; - goto unlock_and_exit; - } - - /* Allocate and init handler object */ - - handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info)); - if (!handler) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - handler->address = address; - handler->context = context; - handler->method_node = gpe_event_info->dispatch.method_node; - - /* Disable the GPE before installing the handler */ - - status = acpi_ev_disable_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - /* Install the handler */ - - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - gpe_event_info->dispatch.handler = handler; - - /* Setup up dispatch flags to indicate handler (vs. method) */ - - gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */ - gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER); - - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - exit: - if (ACPI_FAILURE(status)) - ACPI_EXCEPTION((AE_INFO, status, - "Installing notify handler failed")); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) - -/******************************************************************************* - * - * FUNCTION: acpi_remove_gpe_handler - * - * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT - * defined GPEs) - * gpe_number - The event to remove a handler - * Address - Address of the handler - * - * RETURN: Status - * - * DESCRIPTION: Remove a handler for a General Purpose acpi_event. - * - ******************************************************************************/ -acpi_status -acpi_remove_gpe_handler(acpi_handle gpe_device, - u32 gpe_number, acpi_event_handler address) -{ - struct acpi_gpe_event_info *gpe_event_info; - struct acpi_handler_info *handler; - acpi_status status; - acpi_cpu_flags flags; - - ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler); - - /* Parameter validation */ - - if (!address) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Ensure that we have a valid GPE number */ - - gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); - if (!gpe_event_info) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Make sure that a handler is indeed installed */ - - if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != - ACPI_GPE_DISPATCH_HANDLER) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } - - /* Make sure that the installed handler is the same */ - - if (gpe_event_info->dispatch.handler->address != address) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Disable the GPE before removing the handler */ - - status = acpi_ev_disable_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - /* Make sure all deferred tasks are completed */ - - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - acpi_os_wait_events_complete(NULL); - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Remove the handler */ - - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - handler = gpe_event_info->dispatch.handler; - - /* Restore Method node (if any), set dispatch flags */ - - gpe_event_info->dispatch.method_node = handler->method_node; - gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */ - if (handler->method_node) { - gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD; - } - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - - /* Now we can free the handler object */ - - ACPI_FREE(handler); - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) - -/******************************************************************************* - * - * FUNCTION: acpi_acquire_global_lock - * - * PARAMETERS: Timeout - How long the caller is willing to wait - * Handle - Where the handle to the lock is returned - * (if acquired) - * - * RETURN: Status - * - * DESCRIPTION: Acquire the ACPI Global Lock - * - * Note: Allows callers with the same thread ID to acquire the global lock - * multiple times. In other words, externally, the behavior of the global lock - * is identical to an AML mutex. On the first acquire, a new handle is - * returned. On any subsequent calls to acquire by the same thread, the same - * handle is returned. - * - ******************************************************************************/ -acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) -{ - acpi_status status; - - if (!handle) { - return (AE_BAD_PARAMETER); - } - - /* Must lock interpreter to prevent race conditions */ - - acpi_ex_enter_interpreter(); - - status = acpi_ex_acquire_mutex_object(timeout, - acpi_gbl_global_lock_mutex, - acpi_os_get_thread_id()); - - if (ACPI_SUCCESS(status)) { - - /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */ - - *handle = acpi_gbl_global_lock_handle; - } - - acpi_ex_exit_interpreter(); - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock) - -/******************************************************************************* - * - * FUNCTION: acpi_release_global_lock - * - * PARAMETERS: Handle - Returned from acpi_acquire_global_lock - * - * RETURN: Status - * - * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. - * - ******************************************************************************/ -acpi_status acpi_release_global_lock(u32 handle) -{ - acpi_status status; - - if (!handle || (handle != acpi_gbl_global_lock_handle)) { - return (AE_NOT_ACQUIRED); - } - - status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_release_global_lock) diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c deleted file mode 100644 index f33cc30cb6b8..000000000000 --- a/drivers/acpi/events/evxfevnt.c +++ /dev/null @@ -1,871 +0,0 @@ -/****************************************************************************** - * - * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EVENTS -ACPI_MODULE_NAME("evxfevnt") - -/* Local prototypes */ -acpi_status -acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, void *context); - -/******************************************************************************* - * - * FUNCTION: acpi_enable - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Transfers the system into ACPI mode. - * - ******************************************************************************/ - -acpi_status acpi_enable(void) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(acpi_enable); - - /* ACPI tables must be present */ - - if (!acpi_tb_tables_loaded()) { - return_ACPI_STATUS(AE_NO_ACPI_TABLES); - } - - /* Check current mode */ - - if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) { - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "System is already in ACPI mode\n")); - } else { - /* Transition to ACPI mode */ - - status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not transition to ACPI mode")); - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "Transition to ACPI mode successful\n")); - } - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_enable) - -/******************************************************************************* - * - * FUNCTION: acpi_disable - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode. - * - ******************************************************************************/ -acpi_status acpi_disable(void) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(acpi_disable); - - if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) { - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "System is already in legacy (non-ACPI) mode\n")); - } else { - /* Transition to LEGACY mode */ - - status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY); - - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not exit ACPI mode to legacy mode")); - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n")); - } - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_disable) - -/******************************************************************************* - * - * FUNCTION: acpi_enable_event - * - * PARAMETERS: Event - The fixed eventto be enabled - * Flags - Reserved - * - * RETURN: Status - * - * DESCRIPTION: Enable an ACPI event (fixed) - * - ******************************************************************************/ -acpi_status acpi_enable_event(u32 event, u32 flags) -{ - acpi_status status = AE_OK; - u32 value; - - ACPI_FUNCTION_TRACE(acpi_enable_event); - - /* Decode the Fixed Event */ - - if (event > ACPI_EVENT_MAX) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* - * Enable the requested fixed event (by writing a one to the enable - * register bit) - */ - status = - acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 1); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Make sure that the hardware responded */ - - status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, &value); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (value != 1) { - ACPI_ERROR((AE_INFO, - "Could not enable %s event", - acpi_ut_get_event_name(event))); - return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); - } - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_enable_event) - -/******************************************************************************* - * - * FUNCTION: acpi_set_gpe_type - * - * PARAMETERS: gpe_device - Parent GPE Device - * gpe_number - GPE level within the GPE block - * Type - New GPE type - * - * RETURN: Status - * - * DESCRIPTION: Set the type of an individual GPE - * - ******************************************************************************/ -acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type) -{ - acpi_status status = AE_OK; - struct acpi_gpe_event_info *gpe_event_info; - - ACPI_FUNCTION_TRACE(acpi_set_gpe_type); - - /* Ensure that we have a valid GPE number */ - - gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); - if (!gpe_event_info) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) { - return_ACPI_STATUS(AE_OK); - } - - /* Set the new type (will disable GPE if currently enabled) */ - - status = acpi_ev_set_gpe_type(gpe_event_info, type); - - unlock_and_exit: - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) - -/******************************************************************************* - * - * FUNCTION: acpi_enable_gpe - * - * PARAMETERS: gpe_device - Parent GPE Device - * gpe_number - GPE level within the GPE block - * Flags - Just enable, or also wake enable? - * Called from ISR or not - * - * RETURN: Status - * - * DESCRIPTION: Enable an ACPI event (general purpose) - * - ******************************************************************************/ -acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) -{ - acpi_status status = AE_OK; - acpi_cpu_flags flags; - struct acpi_gpe_event_info *gpe_event_info; - - ACPI_FUNCTION_TRACE(acpi_enable_gpe); - - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - - /* Ensure that we have a valid GPE number */ - - gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); - if (!gpe_event_info) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Perform the enable */ - - status = acpi_ev_enable_gpe(gpe_event_info, TRUE); - - unlock_and_exit: - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_enable_gpe) - -/******************************************************************************* - * - * FUNCTION: acpi_disable_gpe - * - * PARAMETERS: gpe_device - Parent GPE Device - * gpe_number - GPE level within the GPE block - * Flags - Just disable, or also wake disable? - * Called from ISR or not - * - * RETURN: Status - * - * DESCRIPTION: Disable an ACPI event (general purpose) - * - ******************************************************************************/ -acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) -{ - acpi_status status = AE_OK; - acpi_cpu_flags flags; - struct acpi_gpe_event_info *gpe_event_info; - - ACPI_FUNCTION_TRACE(acpi_disable_gpe); - - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - /* Ensure that we have a valid GPE number */ - - gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); - if (!gpe_event_info) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - status = acpi_ev_disable_gpe(gpe_event_info); - -unlock_and_exit: - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_disable_gpe) - -/******************************************************************************* - * - * FUNCTION: acpi_disable_event - * - * PARAMETERS: Event - The fixed eventto be enabled - * Flags - Reserved - * - * RETURN: Status - * - * DESCRIPTION: Disable an ACPI event (fixed) - * - ******************************************************************************/ -acpi_status acpi_disable_event(u32 event, u32 flags) -{ - acpi_status status = AE_OK; - u32 value; - - ACPI_FUNCTION_TRACE(acpi_disable_event); - - /* Decode the Fixed Event */ - - if (event > ACPI_EVENT_MAX) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* - * Disable the requested fixed event (by writing a zero to the enable - * register bit) - */ - status = - acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 0); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, &value); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (value != 0) { - ACPI_ERROR((AE_INFO, - "Could not disable %s events", - acpi_ut_get_event_name(event))); - return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); - } - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_disable_event) - -/******************************************************************************* - * - * FUNCTION: acpi_clear_event - * - * PARAMETERS: Event - The fixed event to be cleared - * - * RETURN: Status - * - * DESCRIPTION: Clear an ACPI event (fixed) - * - ******************************************************************************/ -acpi_status acpi_clear_event(u32 event) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(acpi_clear_event); - - /* Decode the Fixed Event */ - - if (event > ACPI_EVENT_MAX) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* - * Clear the requested fixed event (By writing a one to the status - * register bit) - */ - status = - acpi_set_register(acpi_gbl_fixed_event_info[event]. - status_register_id, 1); - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_clear_event) - -/******************************************************************************* - * - * FUNCTION: acpi_clear_gpe - * - * PARAMETERS: gpe_device - Parent GPE Device - * gpe_number - GPE level within the GPE block - * Flags - Called from an ISR or not - * - * RETURN: Status - * - * DESCRIPTION: Clear an ACPI event (general purpose) - * - ******************************************************************************/ -acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) -{ - acpi_status status = AE_OK; - struct acpi_gpe_event_info *gpe_event_info; - - ACPI_FUNCTION_TRACE(acpi_clear_gpe); - - /* Use semaphore lock if not executing at interrupt level */ - - if (flags & ACPI_NOT_ISR) { - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* Ensure that we have a valid GPE number */ - - gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); - if (!gpe_event_info) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - status = acpi_hw_clear_gpe(gpe_event_info); - - unlock_and_exit: - if (flags & ACPI_NOT_ISR) { - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - } - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_clear_gpe) -/******************************************************************************* - * - * FUNCTION: acpi_get_event_status - * - * PARAMETERS: Event - The fixed event - * event_status - Where the current status of the event will - * be returned - * - * RETURN: Status - * - * DESCRIPTION: Obtains and returns the current status of the event - * - ******************************************************************************/ -acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) -{ - acpi_status status = AE_OK; - u32 value; - - ACPI_FUNCTION_TRACE(acpi_get_event_status); - - if (!event_status) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Decode the Fixed Event */ - - if (event > ACPI_EVENT_MAX) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Get the status of the requested fixed event */ - - status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, &value); - if (ACPI_FAILURE(status)) - return_ACPI_STATUS(status); - - *event_status = value; - - status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. - status_register_id, &value); - if (ACPI_FAILURE(status)) - return_ACPI_STATUS(status); - - if (value) - *event_status |= ACPI_EVENT_FLAG_SET; - - if (acpi_gbl_fixed_event_handlers[event].handler) - *event_status |= ACPI_EVENT_FLAG_HANDLE; - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_event_status) - -/******************************************************************************* - * - * FUNCTION: acpi_get_gpe_status - * - * PARAMETERS: gpe_device - Parent GPE Device - * gpe_number - GPE level within the GPE block - * Flags - Called from an ISR or not - * event_status - Where the current status of the event will - * be returned - * - * RETURN: Status - * - * DESCRIPTION: Get status of an event (general purpose) - * - ******************************************************************************/ -acpi_status -acpi_get_gpe_status(acpi_handle gpe_device, - u32 gpe_number, u32 flags, acpi_event_status * event_status) -{ - acpi_status status = AE_OK; - struct acpi_gpe_event_info *gpe_event_info; - - ACPI_FUNCTION_TRACE(acpi_get_gpe_status); - - /* Use semaphore lock if not executing at interrupt level */ - - if (flags & ACPI_NOT_ISR) { - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* Ensure that we have a valid GPE number */ - - gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); - if (!gpe_event_info) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Obtain status on the requested GPE number */ - - status = acpi_hw_get_gpe_status(gpe_event_info, event_status); - - if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) - *event_status |= ACPI_EVENT_FLAG_HANDLE; - - unlock_and_exit: - if (flags & ACPI_NOT_ISR) { - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - } - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) -/******************************************************************************* - * - * FUNCTION: acpi_install_gpe_block - * - * PARAMETERS: gpe_device - Handle to the parent GPE Block Device - * gpe_block_address - Address and space_iD - * register_count - Number of GPE register pairs in the block - * interrupt_number - H/W interrupt for the block - * - * RETURN: Status - * - * DESCRIPTION: Create and Install a block of GPE registers - * - ******************************************************************************/ -acpi_status -acpi_install_gpe_block(acpi_handle gpe_device, - struct acpi_generic_address *gpe_block_address, - u32 register_count, u32 interrupt_number) -{ - acpi_status status; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - struct acpi_gpe_block_info *gpe_block; - - ACPI_FUNCTION_TRACE(acpi_install_gpe_block); - - if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - node = acpi_ns_map_handle_to_node(gpe_device); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* - * For user-installed GPE Block Devices, the gpe_block_base_number - * is always zero - */ - status = - acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, - interrupt_number, &gpe_block); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - /* Run the _PRW methods and enable the GPEs */ - - status = acpi_ev_initialize_gpe_block(node, gpe_block); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - /* Get the device_object attached to the node */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - - /* No object, create a new one */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - status = - acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - } - - /* Install the GPE block in the device_object */ - - obj_desc->device.gpe_block = gpe_block; - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_install_gpe_block) - -/******************************************************************************* - * - * FUNCTION: acpi_remove_gpe_block - * - * PARAMETERS: gpe_device - Handle to the parent GPE Block Device - * - * RETURN: Status - * - * DESCRIPTION: Remove a previously installed block of GPE registers - * - ******************************************************************************/ -acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - struct acpi_namespace_node *node; - - ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); - - if (!gpe_device) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - node = acpi_ns_map_handle_to_node(gpe_device); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Get the device_object attached to the node */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc || !obj_desc->device.gpe_block) { - return_ACPI_STATUS(AE_NULL_OBJECT); - } - - /* Delete the GPE block (but not the device_object) */ - - status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block); - if (ACPI_SUCCESS(status)) { - obj_desc->device.gpe_block = NULL; - } - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) - -/******************************************************************************* - * - * FUNCTION: acpi_get_gpe_device - * - * PARAMETERS: Index - System GPE index (0-current_gpe_count) - * gpe_device - Where the parent GPE Device is returned - * - * RETURN: Status - * - * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL - * gpe device indicates that the gpe number is contained in one of - * the FADT-defined gpe blocks. Otherwise, the GPE block device. - * - ******************************************************************************/ -acpi_status -acpi_get_gpe_device(u32 index, acpi_handle *gpe_device) -{ - struct acpi_gpe_device_info info; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_get_gpe_device); - - if (!gpe_device) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (index >= acpi_current_gpe_count) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* Setup and walk the GPE list */ - - info.index = index; - info.status = AE_NOT_EXIST; - info.gpe_device = NULL; - info.next_block_base_index = 0; - - status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - *gpe_device = info.gpe_device; - return_ACPI_STATUS(info.status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_gpe_device) - -/******************************************************************************* - * - * FUNCTION: acpi_ev_get_gpe_device - * - * PARAMETERS: GPE_WALK_CALLBACK - * - * RETURN: Status - * - * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE - * block device. NULL if the GPE is one of the FADT-defined GPEs. - * - ******************************************************************************/ -acpi_status -acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, void *context) -{ - struct acpi_gpe_device_info *info = context; - - /* Increment Index by the number of GPEs in this block */ - - info->next_block_base_index += - (gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH); - - if (info->index < info->next_block_base_index) { - /* - * The GPE index is within this block, get the node. Leave the node - * NULL for the FADT-defined GPEs - */ - if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) { - info->gpe_device = gpe_block->node; - } - - info->status = AE_OK; - return (AE_CTRL_END); - } - - return (AE_OK); -} - -/****************************************************************************** - * - * FUNCTION: acpi_disable_all_gpes - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Disable and clear all GPEs in all GPE blocks - * - ******************************************************************************/ - -acpi_status acpi_disable_all_gpes(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_disable_all_gpes); - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_hw_disable_all_gpes(); - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - - return_ACPI_STATUS(status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_enable_all_runtime_gpes - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks - * - ******************************************************************************/ - -acpi_status acpi_enable_all_runtime_gpes(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes); - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_hw_enable_all_runtime_gpes(); - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c deleted file mode 100644 index b8633947391b..000000000000 --- a/drivers/acpi/events/evxfregn.c +++ /dev/null @@ -1,254 +0,0 @@ -/****************************************************************************** - * - * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and - * Address Spaces. - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_EVENTS -ACPI_MODULE_NAME("evxfregn") - -/******************************************************************************* - * - * FUNCTION: acpi_install_address_space_handler - * - * PARAMETERS: Device - Handle for the device - * space_id - The address space ID - * Handler - Address of the handler - * Setup - Address of the setup function - * Context - Value passed to the handler on each access - * - * RETURN: Status - * - * DESCRIPTION: Install a handler for all op_regions of a given space_id. - * - ******************************************************************************/ -acpi_status -acpi_install_address_space_handler(acpi_handle device, - acpi_adr_space_type space_id, - acpi_adr_space_handler handler, - acpi_adr_space_setup setup, void *context) -{ - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_install_address_space_handler); - - /* Parameter validation */ - - if (!device) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Convert and validate the device handle */ - - node = acpi_ns_map_handle_to_node(device); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Install the handler for all Regions for this Space ID */ - - status = - acpi_ev_install_space_handler(node, space_id, handler, setup, - context); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - /* Run all _REG methods for this address space */ - - status = acpi_ev_execute_reg_methods(node, space_id); - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler) - -/******************************************************************************* - * - * FUNCTION: acpi_remove_address_space_handler - * - * PARAMETERS: Device - Handle for the device - * space_id - The address space ID - * Handler - Address of the handler - * - * RETURN: Status - * - * DESCRIPTION: Remove a previously installed handler. - * - ******************************************************************************/ -acpi_status -acpi_remove_address_space_handler(acpi_handle device, - acpi_adr_space_type space_id, - acpi_adr_space_handler handler) -{ - union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj; - union acpi_operand_object *region_obj; - union acpi_operand_object **last_obj_ptr; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler); - - /* Parameter validation */ - - if (!device) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Convert and validate the device handle */ - - node = acpi_ns_map_handle_to_node(device); - if (!node || - ((node->type != ACPI_TYPE_DEVICE) && - (node->type != ACPI_TYPE_PROCESSOR) && - (node->type != ACPI_TYPE_THERMAL) && - (node != acpi_gbl_root_node))) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Make sure the internal object exists */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } - - /* Find the address handler the user requested */ - - handler_obj = obj_desc->device.handler; - last_obj_ptr = &obj_desc->device.handler; - while (handler_obj) { - - /* We have a handler, see if user requested this one */ - - if (handler_obj->address_space.space_id == space_id) { - - /* Handler must be the same as the installed handler */ - - if (handler_obj->address_space.handler != handler) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Matched space_id, first dereference this in the Regions */ - - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Removing address handler %p(%p) for region %s on Device %p(%p)\n", - handler_obj, handler, - acpi_ut_get_region_name(space_id), - node, obj_desc)); - - region_obj = handler_obj->address_space.region_list; - - /* Walk the handler's region list */ - - while (region_obj) { - /* - * First disassociate the handler from the region. - * - * NOTE: this doesn't mean that the region goes away - * The region is just inaccessible as indicated to - * the _REG method - */ - acpi_ev_detach_region(region_obj, TRUE); - - /* - * Walk the list: Just grab the head because the - * detach_region removed the previous head. - */ - region_obj = - handler_obj->address_space.region_list; - - } - - /* Remove this Handler object from the list */ - - *last_obj_ptr = handler_obj->address_space.next; - - /* Now we can delete the handler object */ - - acpi_ut_remove_reference(handler_obj); - goto unlock_and_exit; - } - - /* Walk the linked list of handlers */ - - last_obj_ptr = &handler_obj->address_space.next; - handler_obj = handler_obj->address_space.next; - } - - /* The handler does not exist */ - - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n", - handler, acpi_ut_get_region_name(space_id), space_id, - node, obj_desc)); - - status = AE_NOT_EXIST; - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler) diff --git a/drivers/acpi/executer/Makefile b/drivers/acpi/executer/Makefile deleted file mode 100644 index e09998aa012f..000000000000 --- a/drivers/acpi/executer/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -obj-y := exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\ - exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\ - excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \ - exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o - -EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c deleted file mode 100644 index be32d0105fe2..000000000000 --- a/drivers/acpi/executer/exconfig.c +++ /dev/null @@ -1,536 +0,0 @@ -/****************************************************************************** - * - * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes) - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exconfig") - -/* Local prototypes */ -static acpi_status -acpi_ex_add_table(u32 table_index, - struct acpi_namespace_node *parent_node, - union acpi_operand_object **ddb_handle); - -/******************************************************************************* - * - * FUNCTION: acpi_ex_add_table - * - * PARAMETERS: Table - Pointer to raw table - * parent_node - Where to load the table (scope) - * ddb_handle - Where to return the table handle. - * - * RETURN: Status - * - * DESCRIPTION: Common function to Install and Load an ACPI table with a - * returned table handle. - * - ******************************************************************************/ - -static acpi_status -acpi_ex_add_table(u32 table_index, - struct acpi_namespace_node *parent_node, - union acpi_operand_object **ddb_handle) -{ - acpi_status status; - union acpi_operand_object *obj_desc; - - ACPI_FUNCTION_TRACE(ex_add_table); - - /* Create an object to be the table handle */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); - if (!obj_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Init the table handle */ - - obj_desc->reference.class = ACPI_REFCLASS_TABLE; - *ddb_handle = obj_desc; - - /* Install the new table into the local data structures */ - - obj_desc->reference.value = table_index; - - /* Add the table to the namespace */ - - status = acpi_ns_load_table(table_index, parent_node); - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(obj_desc); - *ddb_handle = NULL; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_load_table_op - * - * PARAMETERS: walk_state - Current state with operands - * return_desc - Where to store the return object - * - * RETURN: Status - * - * DESCRIPTION: Load an ACPI table from the RSDT/XSDT - * - ******************************************************************************/ - -acpi_status -acpi_ex_load_table_op(struct acpi_walk_state *walk_state, - union acpi_operand_object **return_desc) -{ - acpi_status status; - union acpi_operand_object **operand = &walk_state->operands[0]; - struct acpi_namespace_node *parent_node; - struct acpi_namespace_node *start_node; - struct acpi_namespace_node *parameter_node = NULL; - union acpi_operand_object *ddb_handle; - struct acpi_table_header *table; - u32 table_index; - - ACPI_FUNCTION_TRACE(ex_load_table_op); - - /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */ - - if ((operand[0]->string.length > ACPI_NAME_SIZE) || - (operand[1]->string.length > ACPI_OEM_ID_SIZE) || - (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Find the ACPI table in the RSDT/XSDT */ - - status = acpi_tb_find_table(operand[0]->string.pointer, - operand[1]->string.pointer, - operand[2]->string.pointer, &table_index); - if (ACPI_FAILURE(status)) { - if (status != AE_NOT_FOUND) { - return_ACPI_STATUS(status); - } - - /* Table not found, return an Integer=0 and AE_OK */ - - ddb_handle = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!ddb_handle) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - ddb_handle->integer.value = 0; - *return_desc = ddb_handle; - - return_ACPI_STATUS(AE_OK); - } - - /* Default nodes */ - - start_node = walk_state->scope_info->scope.node; - parent_node = acpi_gbl_root_node; - - /* root_path (optional parameter) */ - - if (operand[3]->string.length > 0) { - /* - * Find the node referenced by the root_path_string. This is the - * location within the namespace where the table will be loaded. - */ - status = - acpi_ns_get_node(start_node, operand[3]->string.pointer, - ACPI_NS_SEARCH_PARENT, &parent_node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* parameter_path (optional parameter) */ - - if (operand[4]->string.length > 0) { - if ((operand[4]->string.pointer[0] != '\\') && - (operand[4]->string.pointer[0] != '^')) { - /* - * Path is not absolute, so it will be relative to the node - * referenced by the root_path_string (or the NS root if omitted) - */ - start_node = parent_node; - } - - /* Find the node referenced by the parameter_path_string */ - - status = - acpi_ns_get_node(start_node, operand[4]->string.pointer, - ACPI_NS_SEARCH_PARENT, ¶meter_node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* Load the table into the namespace */ - - status = acpi_ex_add_table(table_index, parent_node, &ddb_handle); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Parameter Data (optional) */ - - if (parameter_node) { - - /* Store the parameter data into the optional parameter object */ - - status = acpi_ex_store(operand[5], - ACPI_CAST_PTR(union acpi_operand_object, - parameter_node), - walk_state); - if (ACPI_FAILURE(status)) { - (void)acpi_ex_unload_table(ddb_handle); - return_ACPI_STATUS(status); - } - } - - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_SUCCESS(status)) { - ACPI_INFO((AE_INFO, - "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]", - table->signature, table->oem_id, - table->oem_table_id)); - } - - /* Invoke table handler if present */ - - if (acpi_gbl_table_handler) { - (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, - acpi_gbl_table_handler_context); - } - - *return_desc = ddb_handle; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_load_op - * - * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be - * obtained - * Target - Where a handle to the table will be stored - * walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Load an ACPI table from a field or operation region - * - * NOTE: Region Fields (Field, bank_field, index_fields) are resolved to buffer - * objects before this code is reached. - * - * If source is an operation region, it must refer to system_memory, as - * per the ACPI specification. - * - ******************************************************************************/ - -acpi_status -acpi_ex_load_op(union acpi_operand_object *obj_desc, - union acpi_operand_object *target, - struct acpi_walk_state *walk_state) -{ - union acpi_operand_object *ddb_handle; - struct acpi_table_header *table; - struct acpi_table_desc table_desc; - u32 table_index; - acpi_status status; - u32 length; - - ACPI_FUNCTION_TRACE(ex_load_op); - - ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); - - /* Source Object can be either an op_region or a Buffer/Field */ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_REGION: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Load table from Region %p\n", obj_desc)); - - /* Region must be system_memory (from ACPI spec) */ - - if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* - * If the Region Address and Length have not been previously evaluated, - * evaluate them now and save the results. - */ - if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { - status = acpi_ds_get_region_arguments(obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Map the table header and get the actual table length. The region - * length is not guaranteed to be the same as the table length. - */ - table = acpi_os_map_memory(obj_desc->region.address, - sizeof(struct acpi_table_header)); - if (!table) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - length = table->length; - acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); - - /* Must have at least an ACPI table header */ - - if (length < sizeof(struct acpi_table_header)) { - return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); - } - - /* - * The memory region is not guaranteed to remain stable and we must - * copy the table to a local buffer. For example, the memory region - * is corrupted after suspend on some machines. Dynamically loaded - * tables are usually small, so this overhead is minimal. - */ - - /* Allocate a buffer for the table */ - - table_desc.pointer = ACPI_ALLOCATE(length); - if (!table_desc.pointer) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Map the entire table and copy it */ - - table = acpi_os_map_memory(obj_desc->region.address, length); - if (!table) { - ACPI_FREE(table_desc.pointer); - return_ACPI_STATUS(AE_NO_MEMORY); - } - - ACPI_MEMCPY(table_desc.pointer, table, length); - acpi_os_unmap_memory(table, length); - - table_desc.address = obj_desc->region.address; - break; - - case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Load table from Buffer or Field %p\n", - obj_desc)); - - /* Must have at least an ACPI table header */ - - if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) { - return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); - } - - /* Get the actual table length from the table header */ - - table = - ACPI_CAST_PTR(struct acpi_table_header, - obj_desc->buffer.pointer); - length = table->length; - - /* Table cannot extend beyond the buffer */ - - if (length > obj_desc->buffer.length) { - return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); - } - if (length < sizeof(struct acpi_table_header)) { - return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); - } - - /* - * Copy the table from the buffer because the buffer could be modified - * or even deleted in the future - */ - table_desc.pointer = ACPI_ALLOCATE(length); - if (!table_desc.pointer) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - ACPI_MEMCPY(table_desc.pointer, table, length); - table_desc.address = ACPI_TO_INTEGER(table_desc.pointer); - break; - - default: - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* Validate table checksum (will not get validated in tb_add_table) */ - - status = acpi_tb_verify_checksum(table_desc.pointer, length); - if (ACPI_FAILURE(status)) { - ACPI_FREE(table_desc.pointer); - return_ACPI_STATUS(status); - } - - /* Complete the table descriptor */ - - table_desc.length = length; - table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; - - /* Install the new table into the local data structures */ - - status = acpi_tb_add_table(&table_desc, &table_index); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* - * Add the table to the namespace. - * - * Note: Load the table objects relative to the root of the namespace. - * This appears to go against the ACPI specification, but we do it for - * compatibility with other ACPI implementations. - */ - status = - acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); - if (ACPI_FAILURE(status)) { - - /* On error, table_ptr was deallocated above */ - - return_ACPI_STATUS(status); - } - - /* Store the ddb_handle into the Target operand */ - - status = acpi_ex_store(ddb_handle, target, walk_state); - if (ACPI_FAILURE(status)) { - (void)acpi_ex_unload_table(ddb_handle); - - /* table_ptr was deallocated above */ - - acpi_ut_remove_reference(ddb_handle); - return_ACPI_STATUS(status); - } - - /* Invoke table handler if present */ - - if (acpi_gbl_table_handler) { - (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, - table_desc.pointer, - acpi_gbl_table_handler_context); - } - - cleanup: - if (ACPI_FAILURE(status)) { - - /* Delete allocated table buffer */ - - acpi_tb_delete_table(&table_desc); - } - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_unload_table - * - * PARAMETERS: ddb_handle - Handle to a previously loaded table - * - * RETURN: Status - * - * DESCRIPTION: Unload an ACPI table - * - ******************************************************************************/ - -acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) -{ - acpi_status status = AE_OK; - union acpi_operand_object *table_desc = ddb_handle; - u32 table_index; - struct acpi_table_header *table; - - ACPI_FUNCTION_TRACE(ex_unload_table); - - /* - * Validate the handle - * Although the handle is partially validated in acpi_ex_reconfiguration(), - * when it calls acpi_ex_resolve_operands(), the handle is more completely - * validated here. - */ - if ((!ddb_handle) || - (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) || - (ACPI_GET_OBJECT_TYPE(ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Get the table index from the ddb_handle */ - - table_index = table_desc->reference.value; - - /* Invoke table handler if present */ - - if (acpi_gbl_table_handler) { - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_SUCCESS(status)) { - (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, - table, - acpi_gbl_table_handler_context); - } - } - - /* - * Delete the entire namespace under this table Node - * (Offset contains the table_id) - */ - acpi_tb_delete_namespace_by_owner(table_index); - (void)acpi_tb_release_owner_id(table_index); - - acpi_tb_set_table_loaded_flag(table_index, FALSE); - - /* Table unloaded, remove a reference to the ddb_handle object */ - - acpi_ut_remove_reference(ddb_handle); - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c deleted file mode 100644 index caeead439e8c..000000000000 --- a/drivers/acpi/executer/exconvrt.c +++ /dev/null @@ -1,692 +0,0 @@ -/****************************************************************************** - * - * Module Name: exconvrt - Object conversion routines - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exconvrt") - -/* Local prototypes */ -static u32 -acpi_ex_convert_to_ascii(acpi_integer integer, - u16 base, u8 * string, u8 max_length); - -/******************************************************************************* - * - * FUNCTION: acpi_ex_convert_to_integer - * - * PARAMETERS: obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String - * result_desc - Where the new Integer object is returned - * Flags - Used for string conversion - * - * RETURN: Status - * - * DESCRIPTION: Convert an ACPI Object to an integer. - * - ******************************************************************************/ - -acpi_status -acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, - union acpi_operand_object **result_desc, u32 flags) -{ - union acpi_operand_object *return_desc; - u8 *pointer; - acpi_integer result; - u32 i; - u32 count; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc); - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_INTEGER: - - /* No conversion necessary */ - - *result_desc = obj_desc; - return_ACPI_STATUS(AE_OK); - - case ACPI_TYPE_BUFFER: - case ACPI_TYPE_STRING: - - /* Note: Takes advantage of common buffer/string fields */ - - pointer = obj_desc->buffer.pointer; - count = obj_desc->buffer.length; - break; - - default: - return_ACPI_STATUS(AE_TYPE); - } - - /* - * Convert the buffer/string to an integer. Note that both buffers and - * strings are treated as raw data - we don't convert ascii to hex for - * strings. - * - * There are two terminating conditions for the loop: - * 1) The size of an integer has been reached, or - * 2) The end of the buffer or string has been reached - */ - result = 0; - - /* String conversion is different than Buffer conversion */ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_STRING: - - /* - * Convert string to an integer - for most cases, the string must be - * hexadecimal as per the ACPI specification. The only exception (as - * of ACPI 3.0) is that the to_integer() operator allows both decimal - * and hexadecimal strings (hex prefixed with "0x"). - */ - status = acpi_ut_strtoul64((char *)pointer, flags, &result); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - break; - - case ACPI_TYPE_BUFFER: - - /* Check for zero-length buffer */ - - if (!count) { - return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); - } - - /* Transfer no more than an integer's worth of data */ - - if (count > acpi_gbl_integer_byte_width) { - count = acpi_gbl_integer_byte_width; - } - - /* - * Convert buffer to an integer - we simply grab enough raw data - * from the buffer to fill an integer - */ - for (i = 0; i < count; i++) { - /* - * Get next byte and shift it into the Result. - * Little endian is used, meaning that the first byte of the buffer - * is the LSB of the integer - */ - result |= (((acpi_integer) pointer[i]) << (i * 8)); - } - break; - - default: - - /* No other types can get here */ - break; - } - - /* Create a new integer */ - - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(result))); - - /* Save the Result */ - - return_desc->integer.value = result; - acpi_ex_truncate_for32bit_table(return_desc); - *result_desc = return_desc; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_convert_to_buffer - * - * PARAMETERS: obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String - * result_desc - Where the new buffer object is returned - * - * RETURN: Status - * - * DESCRIPTION: Convert an ACPI Object to a Buffer - * - ******************************************************************************/ - -acpi_status -acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, - union acpi_operand_object **result_desc) -{ - union acpi_operand_object *return_desc; - u8 *new_buf; - - ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc); - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_BUFFER: - - /* No conversion necessary */ - - *result_desc = obj_desc; - return_ACPI_STATUS(AE_OK); - - case ACPI_TYPE_INTEGER: - - /* - * Create a new Buffer object. - * Need enough space for one integer - */ - return_desc = - acpi_ut_create_buffer_object(acpi_gbl_integer_byte_width); - if (!return_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Copy the integer to the buffer, LSB first */ - - new_buf = return_desc->buffer.pointer; - ACPI_MEMCPY(new_buf, - &obj_desc->integer.value, - acpi_gbl_integer_byte_width); - break; - - case ACPI_TYPE_STRING: - - /* - * Create a new Buffer object - * Size will be the string length - * - * NOTE: Add one to the string length to include the null terminator. - * The ACPI spec is unclear on this subject, but there is existing - * ASL/AML code that depends on the null being transferred to the new - * buffer. - */ - return_desc = acpi_ut_create_buffer_object((acpi_size) - obj_desc->string. - length + 1); - if (!return_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Copy the string to the buffer */ - - new_buf = return_desc->buffer.pointer; - ACPI_STRNCPY((char *)new_buf, (char *)obj_desc->string.pointer, - obj_desc->string.length); - break; - - default: - return_ACPI_STATUS(AE_TYPE); - } - - /* Mark buffer initialized */ - - return_desc->common.flags |= AOPOBJ_DATA_VALID; - *result_desc = return_desc; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_convert_to_ascii - * - * PARAMETERS: Integer - Value to be converted - * Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX - * String - Where the string is returned - * data_width - Size of data item to be converted, in bytes - * - * RETURN: Actual string length - * - * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string - * - ******************************************************************************/ - -static u32 -acpi_ex_convert_to_ascii(acpi_integer integer, - u16 base, u8 * string, u8 data_width) -{ - acpi_integer digit; - u32 i; - u32 j; - u32 k = 0; - u32 hex_length; - u32 decimal_length; - u32 remainder; - u8 supress_zeros; - - ACPI_FUNCTION_ENTRY(); - - switch (base) { - case 10: - - /* Setup max length for the decimal number */ - - switch (data_width) { - case 1: - decimal_length = ACPI_MAX8_DECIMAL_DIGITS; - break; - - case 4: - decimal_length = ACPI_MAX32_DECIMAL_DIGITS; - break; - - case 8: - default: - decimal_length = ACPI_MAX64_DECIMAL_DIGITS; - break; - } - - supress_zeros = TRUE; /* No leading zeros */ - remainder = 0; - - for (i = decimal_length; i > 0; i--) { - - /* Divide by nth factor of 10 */ - - digit = integer; - for (j = 0; j < i; j++) { - (void)acpi_ut_short_divide(digit, 10, &digit, - &remainder); - } - - /* Handle leading zeros */ - - if (remainder != 0) { - supress_zeros = FALSE; - } - - if (!supress_zeros) { - string[k] = (u8) (ACPI_ASCII_ZERO + remainder); - k++; - } - } - break; - - case 16: - - /* hex_length: 2 ascii hex chars per data byte */ - - hex_length = ACPI_MUL_2(data_width); - for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) { - - /* Get one hex digit, most significant digits first */ - - string[k] = - (u8) acpi_ut_hex_to_ascii_char(integer, - ACPI_MUL_4(j)); - k++; - } - break; - - default: - return (0); - } - - /* - * Since leading zeros are suppressed, we must check for the case where - * the integer equals 0 - * - * Finally, null terminate the string and return the length - */ - if (!k) { - string[0] = ACPI_ASCII_ZERO; - k = 1; - } - - string[k] = 0; - return ((u32) k); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_convert_to_string - * - * PARAMETERS: obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String - * result_desc - Where the string object is returned - * Type - String flags (base and conversion type) - * - * RETURN: Status - * - * DESCRIPTION: Convert an ACPI Object to a string - * - ******************************************************************************/ - -acpi_status -acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, - union acpi_operand_object ** result_desc, u32 type) -{ - union acpi_operand_object *return_desc; - u8 *new_buf; - u32 i; - u32 string_length = 0; - u16 base = 16; - u8 separator = ','; - - ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc); - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_STRING: - - /* No conversion necessary */ - - *result_desc = obj_desc; - return_ACPI_STATUS(AE_OK); - - case ACPI_TYPE_INTEGER: - - switch (type) { - case ACPI_EXPLICIT_CONVERT_DECIMAL: - - /* Make room for maximum decimal number */ - - string_length = ACPI_MAX_DECIMAL_DIGITS; - base = 10; - break; - - default: - - /* Two hex string characters for each integer byte */ - - string_length = ACPI_MUL_2(acpi_gbl_integer_byte_width); - break; - } - - /* - * Create a new String - * Need enough space for one ASCII integer (plus null terminator) - */ - return_desc = - acpi_ut_create_string_object((acpi_size) string_length); - if (!return_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - new_buf = return_desc->buffer.pointer; - - /* Convert integer to string */ - - string_length = - acpi_ex_convert_to_ascii(obj_desc->integer.value, base, - new_buf, - acpi_gbl_integer_byte_width); - - /* Null terminate at the correct place */ - - return_desc->string.length = string_length; - new_buf[string_length] = 0; - break; - - case ACPI_TYPE_BUFFER: - - /* Setup string length, base, and separator */ - - switch (type) { - case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */ - /* - * From ACPI: "If Data is a buffer, it is converted to a string of - * decimal values separated by commas." - */ - base = 10; - - /* - * Calculate the final string length. Individual string values - * are variable length (include separator for each) - */ - for (i = 0; i < obj_desc->buffer.length; i++) { - if (obj_desc->buffer.pointer[i] >= 100) { - string_length += 4; - } else if (obj_desc->buffer.pointer[i] >= 10) { - string_length += 3; - } else { - string_length += 2; - } - } - break; - - case ACPI_IMPLICIT_CONVERT_HEX: - /* - * From the ACPI spec: - *"The entire contents of the buffer are converted to a string of - * two-character hexadecimal numbers, each separated by a space." - */ - separator = ' '; - string_length = (obj_desc->buffer.length * 3); - break; - - case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string */ - /* - * From ACPI: "If Data is a buffer, it is converted to a string of - * hexadecimal values separated by commas." - */ - string_length = (obj_desc->buffer.length * 3); - break; - - default: - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* - * Create a new string object and string buffer - * (-1 because of extra separator included in string_length from above) - * Allow creation of zero-length strings from zero-length buffers. - */ - if (string_length) { - string_length--; - } - - return_desc = acpi_ut_create_string_object((acpi_size) - string_length); - if (!return_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - new_buf = return_desc->buffer.pointer; - - /* - * Convert buffer bytes to hex or decimal values - * (separated by commas or spaces) - */ - for (i = 0; i < obj_desc->buffer.length; i++) { - new_buf += acpi_ex_convert_to_ascii((acpi_integer) - obj_desc->buffer. - pointer[i], base, - new_buf, 1); - *new_buf++ = separator; /* each separated by a comma or space */ - } - - /* - * Null terminate the string - * (overwrites final comma/space from above) - */ - if (obj_desc->buffer.length) { - new_buf--; - } - *new_buf = 0; - break; - - default: - return_ACPI_STATUS(AE_TYPE); - } - - *result_desc = return_desc; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_convert_to_target_type - * - * PARAMETERS: destination_type - Current type of the destination - * source_desc - Source object to be converted. - * result_desc - Where the converted object is returned - * walk_state - Current method state - * - * RETURN: Status - * - * DESCRIPTION: Implements "implicit conversion" rules for storing an object. - * - ******************************************************************************/ - -acpi_status -acpi_ex_convert_to_target_type(acpi_object_type destination_type, - union acpi_operand_object *source_desc, - union acpi_operand_object **result_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ex_convert_to_target_type); - - /* Default behavior */ - - *result_desc = source_desc; - - /* - * If required by the target, - * perform implicit conversion on the source before we store it. - */ - switch (GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args)) { - case ARGI_SIMPLE_TARGET: - case ARGI_FIXED_TARGET: - case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ - - switch (destination_type) { - case ACPI_TYPE_LOCAL_REGION_FIELD: - /* - * Named field can always handle conversions - */ - break; - - default: - /* No conversion allowed for these types */ - - if (destination_type != - ACPI_GET_OBJECT_TYPE(source_desc)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Explicit operator, will store (%s) over existing type (%s)\n", - acpi_ut_get_object_type_name - (source_desc), - acpi_ut_get_type_name - (destination_type))); - status = AE_TYPE; - } - } - break; - - case ARGI_TARGETREF: - - switch (destination_type) { - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - /* - * These types require an Integer operand. We can convert - * a Buffer or a String to an Integer if necessary. - */ - status = - acpi_ex_convert_to_integer(source_desc, result_desc, - 16); - break; - - case ACPI_TYPE_STRING: - /* - * The operand must be a String. We can convert an - * Integer or Buffer if necessary - */ - status = - acpi_ex_convert_to_string(source_desc, result_desc, - ACPI_IMPLICIT_CONVERT_HEX); - break; - - case ACPI_TYPE_BUFFER: - /* - * The operand must be a Buffer. We can convert an - * Integer or String if necessary - */ - status = - acpi_ex_convert_to_buffer(source_desc, result_desc); - break; - - default: - ACPI_ERROR((AE_INFO, - "Bad destination type during conversion: %X", - destination_type)); - status = AE_AML_INTERNAL; - break; - } - break; - - case ARGI_REFERENCE: - /* - * create_xxxx_field cases - we are storing the field object into the name - */ - break; - - default: - ACPI_ERROR((AE_INFO, - "Unknown Target type ID 0x%X AmlOpcode %X DestType %s", - GET_CURRENT_ARG_TYPE(walk_state->op_info-> - runtime_args), - walk_state->opcode, - acpi_ut_get_type_name(destination_type))); - status = AE_AML_INTERNAL; - } - - /* - * Source-to-Target conversion semantics: - * - * If conversion to the target type cannot be performed, then simply - * overwrite the target with the new object and type. - */ - if (status == AE_TYPE) { - status = AE_OK; - } - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c deleted file mode 100644 index 5aa65a214fc2..000000000000 --- a/drivers/acpi/executer/excreate.c +++ /dev/null @@ -1,522 +0,0 @@ -/****************************************************************************** - * - * Module Name: excreate - Named object creation - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("excreate") -#ifndef ACPI_NO_METHOD_EXECUTION -/******************************************************************************* - * - * FUNCTION: acpi_ex_create_alias - * - * PARAMETERS: walk_state - Current state, contains operands - * - * RETURN: Status - * - * DESCRIPTION: Create a new named alias - * - ******************************************************************************/ -acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) -{ - struct acpi_namespace_node *target_node; - struct acpi_namespace_node *alias_node; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ex_create_alias); - - /* Get the source/alias operands (both namespace nodes) */ - - alias_node = (struct acpi_namespace_node *)walk_state->operands[0]; - target_node = (struct acpi_namespace_node *)walk_state->operands[1]; - - if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) || - (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { - /* - * Dereference an existing alias so that we don't create a chain - * of aliases. With this code, we guarantee that an alias is - * always exactly one level of indirection away from the - * actual aliased name. - */ - target_node = - ACPI_CAST_PTR(struct acpi_namespace_node, - target_node->object); - } - - /* - * For objects that can never change (i.e., the NS node will - * permanently point to the same object), we can simply attach - * the object to the new NS node. For other objects (such as - * Integers, buffers, etc.), we have to point the Alias node - * to the original Node. - */ - switch (target_node->type) { - - /* For these types, the sub-object can change dynamically via a Store */ - - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - case ACPI_TYPE_PACKAGE: - case ACPI_TYPE_BUFFER_FIELD: - - /* - * These types open a new scope, so we need the NS node in order to access - * any children. - */ - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_POWER: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_THERMAL: - case ACPI_TYPE_LOCAL_SCOPE: - - /* - * The new alias has the type ALIAS and points to the original - * NS node, not the object itself. - */ - alias_node->type = ACPI_TYPE_LOCAL_ALIAS; - alias_node->object = - ACPI_CAST_PTR(union acpi_operand_object, target_node); - break; - - case ACPI_TYPE_METHOD: - - /* - * Control method aliases need to be differentiated - */ - alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; - alias_node->object = - ACPI_CAST_PTR(union acpi_operand_object, target_node); - break; - - default: - - /* Attach the original source object to the new Alias Node */ - - /* - * The new alias assumes the type of the target, and it points - * to the same object. The reference count of the object has an - * additional reference to prevent deletion out from under either the - * target node or the alias Node - */ - status = acpi_ns_attach_object(alias_node, - acpi_ns_get_attached_object - (target_node), - target_node->type); - break; - } - - /* Since both operands are Nodes, we don't need to delete them */ - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_create_event - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Create a new event object - * - ******************************************************************************/ - -acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_operand_object *obj_desc; - - ACPI_FUNCTION_TRACE(ex_create_event); - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * Create the actual OS semaphore, with zero initial units -- meaning - * that the event is created in an unsignalled state - */ - status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, - &obj_desc->event.os_semaphore); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Attach object to the Node */ - - status = - acpi_ns_attach_object((struct acpi_namespace_node *)walk_state-> - operands[0], obj_desc, ACPI_TYPE_EVENT); - - cleanup: - /* - * Remove local reference to the object (on error, will cause deletion - * of both object and semaphore if present.) - */ - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_create_mutex - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Create a new mutex object - * - * Mutex (Name[0], sync_level[1]) - * - ******************************************************************************/ - -acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - union acpi_operand_object *obj_desc; - - ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS); - - /* Create the new mutex object */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Create the actual OS Mutex */ - - status = acpi_os_create_mutex(&obj_desc->mutex.os_mutex); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Init object and attach to NS node */ - - obj_desc->mutex.sync_level = - (u8) walk_state->operands[1]->integer.value; - obj_desc->mutex.node = - (struct acpi_namespace_node *)walk_state->operands[0]; - - status = - acpi_ns_attach_object(obj_desc->mutex.node, obj_desc, - ACPI_TYPE_MUTEX); - - cleanup: - /* - * Remove local reference to the object (on error, will cause deletion - * of both object and semaphore if present.) - */ - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_create_region - * - * PARAMETERS: aml_start - Pointer to the region declaration AML - * aml_length - Max length of the declaration AML - * region_space - space_iD for the region - * walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Create a new operation region object - * - ******************************************************************************/ - -acpi_status -acpi_ex_create_region(u8 * aml_start, - u32 aml_length, - u8 region_space, struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - union acpi_operand_object *region_obj2; - - ACPI_FUNCTION_TRACE(ex_create_region); - - /* Get the Namespace Node */ - - node = walk_state->op->common.node; - - /* - * If the region object is already attached to this node, - * just return - */ - if (acpi_ns_get_attached_object(node)) { - return_ACPI_STATUS(AE_OK); - } - - /* - * Space ID must be one of the predefined IDs, or in the user-defined - * range - */ - if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) && - (region_space < ACPI_USER_REGION_BEGIN)) { - ACPI_ERROR((AE_INFO, "Invalid AddressSpace type %X", - region_space)); - return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); - } - - ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (%X)\n", - acpi_ut_get_region_name(region_space), region_space)); - - /* Create the region descriptor */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * Remember location in AML stream of address & length - * operands since they need to be evaluated at run time. - */ - region_obj2 = obj_desc->common.next_object; - region_obj2->extra.aml_start = aml_start; - region_obj2->extra.aml_length = aml_length; - - /* Init the region from the operands */ - - obj_desc->region.space_id = region_space; - obj_desc->region.address = 0; - obj_desc->region.length = 0; - obj_desc->region.node = node; - - /* Install the new region object in the parent Node */ - - status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION); - - cleanup: - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_create_processor - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Create a new processor object and populate the fields - * - * Processor (Name[0], cpu_iD[1], pblock_addr[2], pblock_length[3]) - * - ******************************************************************************/ - -acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *obj_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state); - - /* Create the processor object */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR); - if (!obj_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Initialize the processor object from the operands */ - - obj_desc->processor.proc_id = (u8) operand[1]->integer.value; - obj_desc->processor.length = (u8) operand[3]->integer.value; - obj_desc->processor.address = - (acpi_io_address) operand[2]->integer.value; - - /* Install the processor object in the parent Node */ - - status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], - obj_desc, ACPI_TYPE_PROCESSOR); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_create_power_resource - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Create a new power_resource object and populate the fields - * - * power_resource (Name[0], system_level[1], resource_order[2]) - * - ******************************************************************************/ - -acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - acpi_status status; - union acpi_operand_object *obj_desc; - - ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state); - - /* Create the power resource object */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER); - if (!obj_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Initialize the power object from the operands */ - - obj_desc->power_resource.system_level = (u8) operand[1]->integer.value; - obj_desc->power_resource.resource_order = - (u16) operand[2]->integer.value; - - /* Install the power resource object in the parent Node */ - - status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], - obj_desc, ACPI_TYPE_POWER); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ex_create_method - * - * PARAMETERS: aml_start - First byte of the method's AML - * aml_length - AML byte count for this method - * walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Create a new method object - * - ******************************************************************************/ - -acpi_status -acpi_ex_create_method(u8 * aml_start, - u32 aml_length, struct acpi_walk_state *walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *obj_desc; - acpi_status status; - u8 method_flags; - - ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state); - - /* Create a new method object */ - - obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto exit; - } - - /* Save the method's AML pointer and length */ - - obj_desc->method.aml_start = aml_start; - obj_desc->method.aml_length = aml_length; - - /* - * Disassemble the method flags. Split off the Arg Count - * for efficiency - */ - method_flags = (u8) operand[1]->integer.value; - - obj_desc->method.method_flags = - (u8) (method_flags & ~AML_METHOD_ARG_COUNT); - obj_desc->method.param_count = - (u8) (method_flags & AML_METHOD_ARG_COUNT); - - /* - * Get the sync_level. If method is serialized, a mutex will be - * created for this method when it is parsed. - */ - if (method_flags & AML_METHOD_SERIALIZED) { - /* - * ACPI 1.0: sync_level = 0 - * ACPI 2.0: sync_level = sync_level in method declaration - */ - obj_desc->method.sync_level = (u8) - ((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4); - } - - /* Attach the new object to the method Node */ - - status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], - obj_desc, ACPI_TYPE_METHOD); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - - exit: - /* Remove a reference to the operand */ - - acpi_ut_remove_reference(operand[1]); - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c deleted file mode 100644 index 8241b9eff6c1..000000000000 --- a/drivers/acpi/executer/exdump.c +++ /dev/null @@ -1,1060 +0,0 @@ -/****************************************************************************** - * - * Module Name: exdump - Interpreter debug output routines - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exdump") - -/* - * The following routines are used for debug output only - */ -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) -/* Local prototypes */ -static void acpi_ex_out_string(char *title, char *value); - -static void acpi_ex_out_pointer(char *title, void *value); - -static void -acpi_ex_dump_object(union acpi_operand_object *obj_desc, - struct acpi_exdump_info *info); - -static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc); - -static void -acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, - u32 level, u32 index); - -/******************************************************************************* - * - * Object Descriptor info tables - * - * Note: The first table entry must be an INIT opcode and must contain - * the table length (number of table entries) - * - ******************************************************************************/ - -static struct acpi_exdump_info acpi_ex_dump_integer[2] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_integer), NULL}, - {ACPI_EXD_UINT64, ACPI_EXD_OFFSET(integer.value), "Value"} -}; - -static struct acpi_exdump_info acpi_ex_dump_string[4] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_string), NULL}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(string.length), "Length"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(string.pointer), "Pointer"}, - {ACPI_EXD_STRING, 0, NULL} -}; - -static struct acpi_exdump_info acpi_ex_dump_buffer[5] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer), NULL}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(buffer.length), "Length"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.pointer), "Pointer"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.node), "Parent Node"}, - {ACPI_EXD_BUFFER, 0, NULL} -}; - -static struct acpi_exdump_info acpi_ex_dump_package[5] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_package), NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(package.flags), "Flags"}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(package.count), "Elements"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(package.elements), "Element List"}, - {ACPI_EXD_PACKAGE, 0, NULL} -}; - -static struct acpi_exdump_info acpi_ex_dump_device[4] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_device), NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.handler), "Handler"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.system_notify), - "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.device_notify), - "Device Notify"} -}; - -static struct acpi_exdump_info acpi_ex_dump_event[2] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_event), NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(event.os_semaphore), "OsSemaphore"} -}; - -static struct acpi_exdump_info acpi_ex_dump_method[8] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "ParamCount"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.sync_level), "Sync Level"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.mutex), "Mutex"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.thread_count), "Thread Count"}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(method.aml_length), "Aml Length"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.aml_start), "Aml Start"} -}; - -static struct acpi_exdump_info acpi_ex_dump_mutex[5] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"}, - {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth), - "Acquire Depth"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"} -}; - -static struct acpi_exdump_info acpi_ex_dump_region[7] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region), NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.space_id), "Space Id"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.flags), "Flags"}, - {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(region.address), "Address"}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(region.length), "Length"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.handler), "Handler"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.next), "Next"} -}; - -static struct acpi_exdump_info acpi_ex_dump_power[5] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_power), NULL}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.system_level), - "System Level"}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.resource_order), - "Resource Order"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.system_notify), - "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.device_notify), - "Device Notify"} -}; - -static struct acpi_exdump_info acpi_ex_dump_processor[7] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_processor), NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.proc_id), "Processor ID"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.length), "Length"}, - {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(processor.address), "Address"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.system_notify), - "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.device_notify), - "Device Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.handler), "Handler"} -}; - -static struct acpi_exdump_info acpi_ex_dump_thermal[4] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_thermal), NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.system_notify), - "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.device_notify), - "Device Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.handler), "Handler"} -}; - -static struct acpi_exdump_info acpi_ex_dump_buffer_field[3] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer_field), NULL}, - {ACPI_EXD_FIELD, 0, NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer_field.buffer_obj), - "Buffer Object"} -}; - -static struct acpi_exdump_info acpi_ex_dump_region_field[3] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region_field), NULL}, - {ACPI_EXD_FIELD, 0, NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"} -}; - -static struct acpi_exdump_info acpi_ex_dump_bank_field[5] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_bank_field), NULL}, - {ACPI_EXD_FIELD, 0, NULL}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(bank_field.value), "Value"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(bank_field.region_obj), - "Region Object"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(bank_field.bank_obj), "Bank Object"} -}; - -static struct acpi_exdump_info acpi_ex_dump_index_field[5] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_bank_field), NULL}, - {ACPI_EXD_FIELD, 0, NULL}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(index_field.value), "Value"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.index_obj), - "Index Object"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.data_obj), "Data Object"} -}; - -static struct acpi_exdump_info acpi_ex_dump_reference[8] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_reference), NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.class), "Class"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.value), "Value"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"}, - {ACPI_EXD_REFERENCE, 0, NULL} -}; - -static struct acpi_exdump_info acpi_ex_dump_address_handler[6] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_address_handler), - NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(address_space.space_id), "Space Id"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.next), "Next"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.region_list), - "Region List"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.node), "Node"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.context), "Context"} -}; - -static struct acpi_exdump_info acpi_ex_dump_notify[3] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_notify), NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.node), "Node"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"} -}; - -/* Miscellaneous tables */ - -static struct acpi_exdump_info acpi_ex_dump_common[4] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_common), NULL}, - {ACPI_EXD_TYPE, 0, NULL}, - {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(common.reference_count), - "Reference Count"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common.flags), "Flags"} -}; - -static struct acpi_exdump_info acpi_ex_dump_field_common[7] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_field_common), NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.field_flags), - "Field Flags"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.access_byte_width), - "Access Byte Width"}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.bit_length), - "Bit Length"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.start_field_bit_offset), - "Field Bit Offset"}, - {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.base_byte_offset), - "Base Byte Offset"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(common_field.node), "Parent Node"} -}; - -static struct acpi_exdump_info acpi_ex_dump_node[5] = { - {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"}, - {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"}, - {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(child), "Child List"}, - {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(peer), "Next Peer"} -}; - -/* Dispatch table, indexed by object type */ - -static struct acpi_exdump_info *acpi_ex_dump_info[] = { - NULL, - acpi_ex_dump_integer, - acpi_ex_dump_string, - acpi_ex_dump_buffer, - acpi_ex_dump_package, - NULL, - acpi_ex_dump_device, - acpi_ex_dump_event, - acpi_ex_dump_method, - acpi_ex_dump_mutex, - acpi_ex_dump_region, - acpi_ex_dump_power, - acpi_ex_dump_processor, - acpi_ex_dump_thermal, - acpi_ex_dump_buffer_field, - NULL, - NULL, - acpi_ex_dump_region_field, - acpi_ex_dump_bank_field, - acpi_ex_dump_index_field, - acpi_ex_dump_reference, - NULL, - NULL, - acpi_ex_dump_notify, - acpi_ex_dump_address_handler, - NULL, - NULL, - NULL -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ex_dump_object - * - * PARAMETERS: obj_desc - Descriptor to dump - * Info - Info table corresponding to this object - * type - * - * RETURN: None - * - * DESCRIPTION: Walk the info table for this object - * - ******************************************************************************/ - -static void -acpi_ex_dump_object(union acpi_operand_object *obj_desc, - struct acpi_exdump_info *info) -{ - u8 *target; - char *name; - u8 count; - - if (!info) { - acpi_os_printf - ("ExDumpObject: Display not implemented for object type %s\n", - acpi_ut_get_object_type_name(obj_desc)); - return; - } - - /* First table entry must contain the table length (# of table entries) */ - - count = info->offset; - - while (count) { - target = ACPI_ADD_PTR(u8, obj_desc, info->offset); - name = info->name; - - switch (info->opcode) { - case ACPI_EXD_INIT: - break; - - case ACPI_EXD_TYPE: - acpi_ex_out_string("Type", - acpi_ut_get_object_type_name - (obj_desc)); - break; - - case ACPI_EXD_UINT8: - - acpi_os_printf("%20s : %2.2X\n", name, *target); - break; - - case ACPI_EXD_UINT16: - - acpi_os_printf("%20s : %4.4X\n", name, - ACPI_GET16(target)); - break; - - case ACPI_EXD_UINT32: - - acpi_os_printf("%20s : %8.8X\n", name, - ACPI_GET32(target)); - break; - - case ACPI_EXD_UINT64: - - acpi_os_printf("%20s : %8.8X%8.8X\n", "Value", - ACPI_FORMAT_UINT64(ACPI_GET64(target))); - break; - - case ACPI_EXD_POINTER: - case ACPI_EXD_ADDRESS: - - acpi_ex_out_pointer(name, - *ACPI_CAST_PTR(void *, target)); - break; - - case ACPI_EXD_STRING: - - acpi_ut_print_string(obj_desc->string.pointer, - ACPI_UINT8_MAX); - acpi_os_printf("\n"); - break; - - case ACPI_EXD_BUFFER: - - ACPI_DUMP_BUFFER(obj_desc->buffer.pointer, - obj_desc->buffer.length); - break; - - case ACPI_EXD_PACKAGE: - - /* Dump the package contents */ - - acpi_os_printf("\nPackage Contents:\n"); - acpi_ex_dump_package_obj(obj_desc, 0, 0); - break; - - case ACPI_EXD_FIELD: - - acpi_ex_dump_object(obj_desc, - acpi_ex_dump_field_common); - break; - - case ACPI_EXD_REFERENCE: - - acpi_ex_out_string("Class Name", - (char *) - acpi_ut_get_reference_name - (obj_desc)); - acpi_ex_dump_reference_obj(obj_desc); - break; - - default: - acpi_os_printf("**** Invalid table opcode [%X] ****\n", - info->opcode); - return; - } - - info++; - count--; - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_dump_operand - * - * PARAMETERS: *obj_desc - Pointer to entry to be dumped - * Depth - Current nesting depth - * - * RETURN: None - * - * DESCRIPTION: Dump an operand object - * - ******************************************************************************/ - -void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) -{ - u32 length; - u32 index; - - ACPI_FUNCTION_NAME(ex_dump_operand) - - if (!((ACPI_LV_EXEC & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { - return; - } - - if (!obj_desc) { - - /* This could be a null element of a package */ - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n")); - return; - } - - if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p Namespace Node: ", - obj_desc)); - ACPI_DUMP_ENTRY(obj_desc, ACPI_LV_EXEC); - return; - } - - if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "%p is not a node or operand object: [%s]\n", - obj_desc, - acpi_ut_get_descriptor_name(obj_desc))); - ACPI_DUMP_BUFFER(obj_desc, sizeof(union acpi_operand_object)); - return; - } - - /* obj_desc is a valid object */ - - if (depth > 0) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%*s[%u] %p ", - depth, " ", depth, obj_desc)); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p ", obj_desc)); - } - - /* Decode object type */ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_LOCAL_REFERENCE: - - acpi_os_printf("Reference: [%s] ", - acpi_ut_get_reference_name(obj_desc)); - - switch (obj_desc->reference.class) { - case ACPI_REFCLASS_DEBUG: - - acpi_os_printf("\n"); - break; - - case ACPI_REFCLASS_INDEX: - - acpi_os_printf("%p\n", obj_desc->reference.object); - break; - - case ACPI_REFCLASS_TABLE: - - acpi_os_printf("Table Index %X\n", - obj_desc->reference.value); - break; - - case ACPI_REFCLASS_REFOF: - - acpi_os_printf("%p [%s]\n", obj_desc->reference.object, - acpi_ut_get_type_name(((union - acpi_operand_object - *) - obj_desc-> - reference. - object)->common. - type)); - break; - - case ACPI_REFCLASS_ARG: - - acpi_os_printf("%X", obj_desc->reference.value); - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { - - /* Value is an Integer */ - - acpi_os_printf(" value is [%8.8X%8.8x]", - ACPI_FORMAT_UINT64(obj_desc-> - integer. - value)); - } - - acpi_os_printf("\n"); - break; - - case ACPI_REFCLASS_LOCAL: - - acpi_os_printf("%X", obj_desc->reference.value); - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { - - /* Value is an Integer */ - - acpi_os_printf(" value is [%8.8X%8.8x]", - ACPI_FORMAT_UINT64(obj_desc-> - integer. - value)); - } - - acpi_os_printf("\n"); - break; - - case ACPI_REFCLASS_NAME: - - acpi_os_printf("- [%4.4s]\n", - obj_desc->reference.node->name.ascii); - break; - - default: /* Unknown reference class */ - - acpi_os_printf("%2.2X\n", obj_desc->reference.class); - break; - } - break; - - case ACPI_TYPE_BUFFER: - - acpi_os_printf("Buffer length %.2X @ %p\n", - obj_desc->buffer.length, - obj_desc->buffer.pointer); - - /* Debug only -- dump the buffer contents */ - - if (obj_desc->buffer.pointer) { - length = obj_desc->buffer.length; - if (length > 128) { - length = 128; - } - - acpi_os_printf - ("Buffer Contents: (displaying length 0x%.2X)\n", - length); - ACPI_DUMP_BUFFER(obj_desc->buffer.pointer, length); - } - break; - - case ACPI_TYPE_INTEGER: - - acpi_os_printf("Integer %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(obj_desc->integer.value)); - break; - - case ACPI_TYPE_PACKAGE: - - acpi_os_printf("Package [Len %X] ElementArray %p\n", - obj_desc->package.count, - obj_desc->package.elements); - - /* - * If elements exist, package element pointer is valid, - * and debug_level exceeds 1, dump package's elements. - */ - if (obj_desc->package.count && - obj_desc->package.elements && acpi_dbg_level > 1) { - for (index = 0; index < obj_desc->package.count; - index++) { - acpi_ex_dump_operand(obj_desc->package. - elements[index], - depth + 1); - } - } - break; - - case ACPI_TYPE_REGION: - - acpi_os_printf("Region %s (%X)", - acpi_ut_get_region_name(obj_desc->region. - space_id), - obj_desc->region.space_id); - - /* - * If the address and length have not been evaluated, - * don't print them. - */ - if (!(obj_desc->region.flags & AOPOBJ_DATA_VALID)) { - acpi_os_printf("\n"); - } else { - acpi_os_printf(" base %8.8X%8.8X Length %X\n", - ACPI_FORMAT_NATIVE_UINT(obj_desc->region. - address), - obj_desc->region.length); - } - break; - - case ACPI_TYPE_STRING: - - acpi_os_printf("String length %X @ %p ", - obj_desc->string.length, - obj_desc->string.pointer); - - acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); - acpi_os_printf("\n"); - break; - - case ACPI_TYPE_LOCAL_BANK_FIELD: - - acpi_os_printf("BankField\n"); - break; - - case ACPI_TYPE_LOCAL_REGION_FIELD: - - acpi_os_printf - ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n", - obj_desc->field.bit_length, - obj_desc->field.access_byte_width, - obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK, - obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK, - obj_desc->field.base_byte_offset, - obj_desc->field.start_field_bit_offset); - - acpi_ex_dump_operand(obj_desc->field.region_obj, depth + 1); - break; - - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - acpi_os_printf("IndexField\n"); - break; - - case ACPI_TYPE_BUFFER_FIELD: - - acpi_os_printf("BufferField: %X bits at byte %X bit %X of\n", - obj_desc->buffer_field.bit_length, - obj_desc->buffer_field.base_byte_offset, - obj_desc->buffer_field.start_field_bit_offset); - - if (!obj_desc->buffer_field.buffer_obj) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL*\n")); - } else - if (ACPI_GET_OBJECT_TYPE(obj_desc->buffer_field.buffer_obj) - != ACPI_TYPE_BUFFER) { - acpi_os_printf("*not a Buffer*\n"); - } else { - acpi_ex_dump_operand(obj_desc->buffer_field.buffer_obj, - depth + 1); - } - break; - - case ACPI_TYPE_EVENT: - - acpi_os_printf("Event\n"); - break; - - case ACPI_TYPE_METHOD: - - acpi_os_printf("Method(%X) @ %p:%X\n", - obj_desc->method.param_count, - obj_desc->method.aml_start, - obj_desc->method.aml_length); - break; - - case ACPI_TYPE_MUTEX: - - acpi_os_printf("Mutex\n"); - break; - - case ACPI_TYPE_DEVICE: - - acpi_os_printf("Device\n"); - break; - - case ACPI_TYPE_POWER: - - acpi_os_printf("Power\n"); - break; - - case ACPI_TYPE_PROCESSOR: - - acpi_os_printf("Processor\n"); - break; - - case ACPI_TYPE_THERMAL: - - acpi_os_printf("Thermal\n"); - break; - - default: - /* Unknown Type */ - - acpi_os_printf("Unknown Type %X\n", - ACPI_GET_OBJECT_TYPE(obj_desc)); - break; - } - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_dump_operands - * - * PARAMETERS: Operands - A list of Operand objects - * opcode_name - AML opcode name - * num_operands - Operand count for this opcode - * - * DESCRIPTION: Dump the operands associated with the opcode - * - ******************************************************************************/ - -void -acpi_ex_dump_operands(union acpi_operand_object **operands, - const char *opcode_name, u32 num_operands) -{ - ACPI_FUNCTION_NAME(ex_dump_operands); - - if (!opcode_name) { - opcode_name = "UNKNOWN"; - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "**** Start operand dump for opcode [%s], %d operands\n", - opcode_name, num_operands)); - - if (num_operands == 0) { - num_operands = 1; - } - - /* Dump the individual operands */ - - while (num_operands) { - acpi_ex_dump_operand(*operands, 0); - operands++; - num_operands--; - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "**** End operand dump for [%s]\n", opcode_name)); - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_out* functions - * - * PARAMETERS: Title - Descriptive text - * Value - Value to be displayed - * - * DESCRIPTION: Object dump output formatting functions. These functions - * reduce the number of format strings required and keeps them - * all in one place for easy modification. - * - ******************************************************************************/ - -static void acpi_ex_out_string(char *title, char *value) -{ - acpi_os_printf("%20s : %s\n", title, value); -} - -static void acpi_ex_out_pointer(char *title, void *value) -{ - acpi_os_printf("%20s : %p\n", title, value); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_dump_namespace_node - * - * PARAMETERS: Node - Descriptor to dump - * Flags - Force display if TRUE - * - * DESCRIPTION: Dumps the members of the given.Node - * - ******************************************************************************/ - -void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags) -{ - - ACPI_FUNCTION_ENTRY(); - - if (!flags) { - if (!((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { - return; - } - } - - acpi_os_printf("%20s : %4.4s\n", "Name", acpi_ut_get_node_name(node)); - acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type)); - acpi_ex_out_pointer("Attached Object", - acpi_ns_get_attached_object(node)); - acpi_ex_out_pointer("Parent", acpi_ns_get_parent_node(node)); - - acpi_ex_dump_object(ACPI_CAST_PTR(union acpi_operand_object, node), - acpi_ex_dump_node); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_dump_reference_obj - * - * PARAMETERS: Object - Descriptor to dump - * - * DESCRIPTION: Dumps a reference object - * - ******************************************************************************/ - -static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) -{ - struct acpi_buffer ret_buf; - acpi_status status; - - ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; - - if (obj_desc->reference.class == ACPI_REFCLASS_NAME) { - acpi_os_printf(" %p ", obj_desc->reference.node); - - status = - acpi_ns_handle_to_pathname(obj_desc->reference.node, - &ret_buf); - if (ACPI_FAILURE(status)) { - acpi_os_printf(" Could not convert name to pathname\n"); - } else { - acpi_os_printf("%s\n", (char *)ret_buf.pointer); - ACPI_FREE(ret_buf.pointer); - } - } else if (obj_desc->reference.object) { - if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == - ACPI_DESC_TYPE_OPERAND) { - acpi_os_printf(" Target: %p", - obj_desc->reference.object); - if (obj_desc->reference.class == ACPI_REFCLASS_TABLE) { - acpi_os_printf(" Table Index: %X\n", - obj_desc->reference.value); - } else { - acpi_os_printf(" Target: %p [%s]\n", - obj_desc->reference.object, - acpi_ut_get_type_name(((union - acpi_operand_object - *) - obj_desc-> - reference. - object)-> - common. - type)); - } - } else { - acpi_os_printf(" Target: %p\n", - obj_desc->reference.object); - } - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_dump_package_obj - * - * PARAMETERS: obj_desc - Descriptor to dump - * Level - Indentation Level - * Index - Package index for this object - * - * DESCRIPTION: Dumps the elements of the package - * - ******************************************************************************/ - -static void -acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, - u32 level, u32 index) -{ - u32 i; - - /* Indentation and index output */ - - if (level > 0) { - for (i = 0; i < level; i++) { - acpi_os_printf(" "); - } - - acpi_os_printf("[%.2d] ", index); - } - - acpi_os_printf("%p ", obj_desc); - - /* Null package elements are allowed */ - - if (!obj_desc) { - acpi_os_printf("[Null Object]\n"); - return; - } - - /* Packages may only contain a few object types */ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_INTEGER: - - acpi_os_printf("[Integer] = %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(obj_desc->integer.value)); - break; - - case ACPI_TYPE_STRING: - - acpi_os_printf("[String] Value: "); - for (i = 0; i < obj_desc->string.length; i++) { - acpi_os_printf("%c", obj_desc->string.pointer[i]); - } - acpi_os_printf("\n"); - break; - - case ACPI_TYPE_BUFFER: - - acpi_os_printf("[Buffer] Length %.2X = ", - obj_desc->buffer.length); - if (obj_desc->buffer.length) { - acpi_ut_dump_buffer(ACPI_CAST_PTR - (u8, obj_desc->buffer.pointer), - obj_desc->buffer.length, - DB_DWORD_DISPLAY, _COMPONENT); - } else { - acpi_os_printf("\n"); - } - break; - - case ACPI_TYPE_PACKAGE: - - acpi_os_printf("[Package] Contains %d Elements:\n", - obj_desc->package.count); - - for (i = 0; i < obj_desc->package.count; i++) { - acpi_ex_dump_package_obj(obj_desc->package.elements[i], - level + 1, i); - } - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - - acpi_os_printf("[Object Reference] Type [%s] %2.2X", - acpi_ut_get_reference_name(obj_desc), - obj_desc->reference.class); - acpi_ex_dump_reference_obj(obj_desc); - break; - - default: - - acpi_os_printf("[Unknown Type] %X\n", - ACPI_GET_OBJECT_TYPE(obj_desc)); - break; - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_dump_object_descriptor - * - * PARAMETERS: obj_desc - Descriptor to dump - * Flags - Force display if TRUE - * - * DESCRIPTION: Dumps the members of the object descriptor given. - * - ******************************************************************************/ - -void -acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) -{ - ACPI_FUNCTION_TRACE(ex_dump_object_descriptor); - - if (!obj_desc) { - return_VOID; - } - - if (!flags) { - if (!((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { - return_VOID; - } - } - - if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) { - acpi_ex_dump_namespace_node((struct acpi_namespace_node *) - obj_desc, flags); - - acpi_os_printf("\nAttached Object (%p):\n", - ((struct acpi_namespace_node *)obj_desc)-> - object); - - acpi_ex_dump_object_descriptor(((struct acpi_namespace_node *) - obj_desc)->object, flags); - return_VOID; - } - - if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) { - acpi_os_printf - ("ExDumpObjectDescriptor: %p is not an ACPI operand object: [%s]\n", - obj_desc, acpi_ut_get_descriptor_name(obj_desc)); - return_VOID; - } - - if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) { - return_VOID; - } - - /* Common Fields */ - - acpi_ex_dump_object(obj_desc, acpi_ex_dump_common); - - /* Object-specific fields */ - - acpi_ex_dump_object(obj_desc, acpi_ex_dump_info[obj_desc->common.type]); - return_VOID; -} - -#endif diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c deleted file mode 100644 index 7b6df031039d..000000000000 --- a/drivers/acpi/executer/exfield.c +++ /dev/null @@ -1,340 +0,0 @@ -/****************************************************************************** - * - * Module Name: exfield - ACPI AML (p-code) execution - field manipulation - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exfield") - -/******************************************************************************* - * - * FUNCTION: acpi_ex_read_data_from_field - * - * PARAMETERS: walk_state - Current execution state - * obj_desc - The named field - * ret_buffer_desc - Where the return data object is stored - * - * RETURN: Status - * - * DESCRIPTION: Read from a named field. Returns either an Integer or a - * Buffer, depending on the size of the field. - * - ******************************************************************************/ -acpi_status -acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, - union acpi_operand_object *obj_desc, - union acpi_operand_object **ret_buffer_desc) -{ - acpi_status status; - union acpi_operand_object *buffer_desc; - acpi_size length; - void *buffer; - - ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); - - /* Parameter validation */ - - if (!obj_desc) { - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - if (!ret_buffer_desc) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { - /* - * If the buffer_field arguments have not been previously evaluated, - * evaluate them now and save the results. - */ - if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { - status = acpi_ds_get_buffer_field_arguments(obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - } else - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) - && (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_SMBUS)) { - /* - * This is an SMBus read. We must create a buffer to hold the data - * and directly access the region handler. - */ - buffer_desc = - acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE); - if (!buffer_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Lock entire transaction if requested */ - - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); - - /* - * Perform the read. - * Note: Smbus protocol value is passed in upper 16-bits of Function - */ - status = acpi_ex_access_region(obj_desc, 0, - ACPI_CAST_PTR(acpi_integer, - buffer_desc-> - buffer.pointer), - ACPI_READ | (obj_desc->field. - attribute << 16)); - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - goto exit; - } - - /* - * Allocate a buffer for the contents of the field. - * - * If the field is larger than the size of an acpi_integer, create - * a BUFFER to hold it. Otherwise, use an INTEGER. This allows - * the use of arithmetic operators on the returned value if the - * field size is equal or smaller than an Integer. - * - * Note: Field.length is in bits. - */ - length = - (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length); - if (length > acpi_gbl_integer_byte_width) { - - /* Field is too large for an Integer, create a Buffer instead */ - - buffer_desc = acpi_ut_create_buffer_object(length); - if (!buffer_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - buffer = buffer_desc->buffer.pointer; - } else { - /* Field will fit within an Integer (normal case) */ - - buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!buffer_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - length = acpi_gbl_integer_byte_width; - buffer_desc->integer.value = 0; - buffer = &buffer_desc->integer.value; - } - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", - obj_desc, ACPI_GET_OBJECT_TYPE(obj_desc), buffer, - (u32) length)); - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", - obj_desc->common_field.bit_length, - obj_desc->common_field.start_field_bit_offset, - obj_desc->common_field.base_byte_offset)); - - /* Lock entire transaction if requested */ - - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); - - /* Read from the field */ - - status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - - exit: - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(buffer_desc); - } else { - *ret_buffer_desc = buffer_desc; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_write_data_to_field - * - * PARAMETERS: source_desc - Contains data to write - * obj_desc - The named field - * result_desc - Where the return value is returned, if any - * - * RETURN: Status - * - * DESCRIPTION: Write to a named field - * - ******************************************************************************/ - -acpi_status -acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, - union acpi_operand_object *obj_desc, - union acpi_operand_object **result_desc) -{ - acpi_status status; - u32 length; - void *buffer; - union acpi_operand_object *buffer_desc; - - ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); - - /* Parameter validation */ - - if (!source_desc || !obj_desc) { - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { - /* - * If the buffer_field arguments have not been previously evaluated, - * evaluate them now and save the results. - */ - if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { - status = acpi_ds_get_buffer_field_arguments(obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - } else - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) - && (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_SMBUS)) { - /* - * This is an SMBus write. We will bypass the entire field mechanism - * and handoff the buffer directly to the handler. - * - * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE). - */ - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) { - ACPI_ERROR((AE_INFO, - "SMBus write requires Buffer, found type %s", - acpi_ut_get_object_type_name(source_desc))); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) { - ACPI_ERROR((AE_INFO, - "SMBus write requires Buffer of length %X, found length %X", - ACPI_SMBUS_BUFFER_SIZE, - source_desc->buffer.length)); - - return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); - } - - buffer_desc = - acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE); - if (!buffer_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - buffer = buffer_desc->buffer.pointer; - ACPI_MEMCPY(buffer, source_desc->buffer.pointer, - ACPI_SMBUS_BUFFER_SIZE); - - /* Lock entire transaction if requested */ - - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); - - /* - * Perform the write (returns status and perhaps data in the - * same buffer) - * Note: SMBus protocol type is passed in upper 16-bits of Function. - */ - status = acpi_ex_access_region(obj_desc, 0, - (acpi_integer *) buffer, - ACPI_WRITE | (obj_desc->field. - attribute << 16)); - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - - *result_desc = buffer_desc; - return_ACPI_STATUS(status); - } - - /* Get a pointer to the data to be written */ - - switch (ACPI_GET_OBJECT_TYPE(source_desc)) { - case ACPI_TYPE_INTEGER: - buffer = &source_desc->integer.value; - length = sizeof(source_desc->integer.value); - break; - - case ACPI_TYPE_BUFFER: - buffer = source_desc->buffer.pointer; - length = source_desc->buffer.length; - break; - - case ACPI_TYPE_STRING: - buffer = source_desc->string.pointer; - length = source_desc->string.length; - break; - - default: - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", - source_desc, - acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE - (source_desc)), - ACPI_GET_OBJECT_TYPE(source_desc), buffer, length)); - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", - obj_desc, - acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)), - ACPI_GET_OBJECT_TYPE(obj_desc), - obj_desc->common_field.bit_length, - obj_desc->common_field.start_field_bit_offset, - obj_desc->common_field.base_byte_offset)); - - /* Lock entire transaction if requested */ - - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); - - /* Write to the field */ - - status = acpi_ex_insert_into_field(obj_desc, buffer, length); - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c deleted file mode 100644 index 33cd17a1064f..000000000000 --- a/drivers/acpi/executer/exfldio.c +++ /dev/null @@ -1,961 +0,0 @@ -/****************************************************************************** - * - * Module Name: exfldio - Aml Field I/O - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exfldio") - -/* Local prototypes */ -static acpi_status -acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, - u32 field_datum_byte_offset, - acpi_integer * value, u32 read_write); - -static u8 -acpi_ex_register_overflow(union acpi_operand_object *obj_desc, - acpi_integer value); - -static acpi_status -acpi_ex_setup_region(union acpi_operand_object *obj_desc, - u32 field_datum_byte_offset); - -/******************************************************************************* - * - * FUNCTION: acpi_ex_setup_region - * - * PARAMETERS: obj_desc - Field to be read or written - * field_datum_byte_offset - Byte offset of this datum within the - * parent field - * - * RETURN: Status - * - * DESCRIPTION: Common processing for acpi_ex_extract_from_field and - * acpi_ex_insert_into_field. Initialize the Region if necessary and - * validate the request. - * - ******************************************************************************/ - -static acpi_status -acpi_ex_setup_region(union acpi_operand_object *obj_desc, - u32 field_datum_byte_offset) -{ - acpi_status status = AE_OK; - union acpi_operand_object *rgn_desc; - - ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset); - - rgn_desc = obj_desc->common_field.region_obj; - - /* We must have a valid region */ - - if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) { - ACPI_ERROR((AE_INFO, "Needed Region, found type %X (%s)", - ACPI_GET_OBJECT_TYPE(rgn_desc), - acpi_ut_get_object_type_name(rgn_desc))); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* - * If the Region Address and Length have not been previously evaluated, - * evaluate them now and save the results. - */ - if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) { - status = acpi_ds_get_region_arguments(rgn_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* Exit if Address/Length have been disallowed by the host OS */ - - if (rgn_desc->common.flags & AOPOBJ_INVALID) { - return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); - } - - /* - * Exit now for SMBus address space, it has a non-linear address space - * and the request cannot be directly validated - */ - if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { - - /* SMBus has a non-linear address space */ - - return_ACPI_STATUS(AE_OK); - } -#ifdef ACPI_UNDER_DEVELOPMENT - /* - * If the Field access is any_acc, we can now compute the optimal - * access (because we know know the length of the parent region) - */ - if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } -#endif - - /* - * Validate the request. The entire request from the byte offset for a - * length of one field datum (access width) must fit within the region. - * (Region length is specified in bytes) - */ - if (rgn_desc->region.length < - (obj_desc->common_field.base_byte_offset + - field_datum_byte_offset + - obj_desc->common_field.access_byte_width)) { - if (acpi_gbl_enable_interpreter_slack) { - /* - * Slack mode only: We will go ahead and allow access to this - * field if it is within the region length rounded up to the next - * access width boundary. acpi_size cast for 64-bit compile. - */ - if (ACPI_ROUND_UP(rgn_desc->region.length, - obj_desc->common_field. - access_byte_width) >= - ((acpi_size) obj_desc->common_field. - base_byte_offset + - obj_desc->common_field.access_byte_width + - field_datum_byte_offset)) { - return_ACPI_STATUS(AE_OK); - } - } - - if (rgn_desc->region.length < - obj_desc->common_field.access_byte_width) { - /* - * This is the case where the access_type (acc_word, etc.) is wider - * than the region itself. For example, a region of length one - * byte, and a field with Dword access specified. - */ - ACPI_ERROR((AE_INFO, - "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)", - acpi_ut_get_node_name(obj_desc-> - common_field.node), - obj_desc->common_field.access_byte_width, - acpi_ut_get_node_name(rgn_desc->region. - node), - rgn_desc->region.length)); - } - - /* - * Offset rounded up to next multiple of field width - * exceeds region length, indicate an error - */ - ACPI_ERROR((AE_INFO, - "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)", - acpi_ut_get_node_name(obj_desc->common_field.node), - obj_desc->common_field.base_byte_offset, - field_datum_byte_offset, - obj_desc->common_field.access_byte_width, - acpi_ut_get_node_name(rgn_desc->region.node), - rgn_desc->region.length)); - - return_ACPI_STATUS(AE_AML_REGION_LIMIT); - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_access_region - * - * PARAMETERS: obj_desc - Field to be read - * field_datum_byte_offset - Byte offset of this datum within the - * parent field - * Value - Where to store value (must at least - * the size of acpi_integer) - * Function - Read or Write flag plus other region- - * dependent flags - * - * RETURN: Status - * - * DESCRIPTION: Read or Write a single field datum to an Operation Region. - * - ******************************************************************************/ - -acpi_status -acpi_ex_access_region(union acpi_operand_object *obj_desc, - u32 field_datum_byte_offset, - acpi_integer * value, u32 function) -{ - acpi_status status; - union acpi_operand_object *rgn_desc; - acpi_physical_address address; - - ACPI_FUNCTION_TRACE(ex_access_region); - - /* - * Ensure that the region operands are fully evaluated and verify - * the validity of the request - */ - status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * The physical address of this field datum is: - * - * 1) The base of the region, plus - * 2) The base offset of the field, plus - * 3) The current offset into the field - */ - rgn_desc = obj_desc->common_field.region_obj; - address = rgn_desc->region.address + - obj_desc->common_field.base_byte_offset + field_datum_byte_offset; - - if ((function & ACPI_IO_MASK) == ACPI_READ) { - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]")); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]")); - } - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, - " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n", - acpi_ut_get_region_name(rgn_desc->region. - space_id), - rgn_desc->region.space_id, - obj_desc->common_field.access_byte_width, - obj_desc->common_field.base_byte_offset, - field_datum_byte_offset, ACPI_CAST_PTR(void, - address))); - - /* Invoke the appropriate address_space/op_region handler */ - - status = acpi_ev_address_space_dispatch(rgn_desc, function, - address, - ACPI_MUL_8(obj_desc-> - common_field. - access_byte_width), - value); - - if (ACPI_FAILURE(status)) { - if (status == AE_NOT_IMPLEMENTED) { - ACPI_ERROR((AE_INFO, - "Region %s(%X) not implemented", - acpi_ut_get_region_name(rgn_desc->region. - space_id), - rgn_desc->region.space_id)); - } else if (status == AE_NOT_EXIST) { - ACPI_ERROR((AE_INFO, - "Region %s(%X) has no handler", - acpi_ut_get_region_name(rgn_desc->region. - space_id), - rgn_desc->region.space_id)); - } - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_register_overflow - * - * PARAMETERS: obj_desc - Register(Field) to be written - * Value - Value to be stored - * - * RETURN: TRUE if value overflows the field, FALSE otherwise - * - * DESCRIPTION: Check if a value is out of range of the field being written. - * Used to check if the values written to Index and Bank registers - * are out of range. Normally, the value is simply truncated - * to fit the field, but this case is most likely a serious - * coding error in the ASL. - * - ******************************************************************************/ - -static u8 -acpi_ex_register_overflow(union acpi_operand_object *obj_desc, - acpi_integer value) -{ - - if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) { - /* - * The field is large enough to hold the maximum integer, so we can - * never overflow it. - */ - return (FALSE); - } - - if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) { - /* - * The Value is larger than the maximum value that can fit into - * the register. - */ - return (TRUE); - } - - /* The Value will fit into the field with no truncation */ - - return (FALSE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_field_datum_io - * - * PARAMETERS: obj_desc - Field to be read - * field_datum_byte_offset - Byte offset of this datum within the - * parent field - * Value - Where to store value (must be 64 bits) - * read_write - Read or Write flag - * - * RETURN: Status - * - * DESCRIPTION: Read or Write a single datum of a field. The field_type is - * demultiplexed here to handle the different types of fields - * (buffer_field, region_field, index_field, bank_field) - * - ******************************************************************************/ - -static acpi_status -acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, - u32 field_datum_byte_offset, - acpi_integer * value, u32 read_write) -{ - acpi_status status; - acpi_integer local_value; - - ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset); - - if (read_write == ACPI_READ) { - if (!value) { - local_value = 0; - - /* To support reads without saving return value */ - value = &local_value; - } - - /* Clear the entire return buffer first, [Very Important!] */ - - *value = 0; - } - - /* - * The four types of fields are: - * - * buffer_field - Read/write from/to a Buffer - * region_field - Read/write from/to a Operation Region. - * bank_field - Write to a Bank Register, then read/write from/to an - * operation_region - * index_field - Write to an Index Register, then read/write from/to a - * Data Register - */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_BUFFER_FIELD: - /* - * If the buffer_field arguments have not been previously evaluated, - * evaluate them now and save the results. - */ - if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { - status = acpi_ds_get_buffer_field_arguments(obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - if (read_write == ACPI_READ) { - /* - * Copy the data from the source buffer. - * Length is the field width in bytes. - */ - ACPI_MEMCPY(value, - (obj_desc->buffer_field.buffer_obj)->buffer. - pointer + - obj_desc->buffer_field.base_byte_offset + - field_datum_byte_offset, - obj_desc->common_field.access_byte_width); - } else { - /* - * Copy the data to the target buffer. - * Length is the field width in bytes. - */ - ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer. - pointer + - obj_desc->buffer_field.base_byte_offset + - field_datum_byte_offset, value, - obj_desc->common_field.access_byte_width); - } - - status = AE_OK; - break; - - case ACPI_TYPE_LOCAL_BANK_FIELD: - - /* - * Ensure that the bank_value is not beyond the capacity of - * the register - */ - if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj, - (acpi_integer) obj_desc-> - bank_field.value)) { - return_ACPI_STATUS(AE_AML_REGISTER_LIMIT); - } - - /* - * For bank_fields, we must write the bank_value to the bank_register - * (itself a region_field) before we can access the data. - */ - status = - acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj, - &obj_desc->bank_field.value, - sizeof(obj_desc->bank_field. - value)); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Now that the Bank has been selected, fall through to the - * region_field case and write the datum to the Operation Region - */ - - /*lint -fallthrough */ - - case ACPI_TYPE_LOCAL_REGION_FIELD: - /* - * For simple region_fields, we just directly access the owning - * Operation Region. - */ - status = - acpi_ex_access_region(obj_desc, field_datum_byte_offset, - value, read_write); - break; - - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - /* - * Ensure that the index_value is not beyond the capacity of - * the register - */ - if (acpi_ex_register_overflow(obj_desc->index_field.index_obj, - (acpi_integer) obj_desc-> - index_field.value)) { - return_ACPI_STATUS(AE_AML_REGISTER_LIMIT); - } - - /* Write the index value to the index_register (itself a region_field) */ - - field_datum_byte_offset += obj_desc->index_field.value; - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Write to Index Register: Value %8.8X\n", - field_datum_byte_offset)); - - status = - acpi_ex_insert_into_field(obj_desc->index_field.index_obj, - &field_datum_byte_offset, - sizeof(field_datum_byte_offset)); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (read_write == ACPI_READ) { - - /* Read the datum from the data_register */ - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Read from Data Register\n")); - - status = - acpi_ex_extract_from_field(obj_desc->index_field. - data_obj, value, - sizeof(acpi_integer)); - } else { - /* Write the datum to the data_register */ - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Write to Data Register: Value %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(*value))); - - status = - acpi_ex_insert_into_field(obj_desc->index_field. - data_obj, value, - sizeof(acpi_integer)); - } - break; - - default: - - ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %X", - ACPI_GET_OBJECT_TYPE(obj_desc))); - status = AE_AML_INTERNAL; - break; - } - - if (ACPI_SUCCESS(status)) { - if (read_write == ACPI_READ) { - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Value Read %8.8X%8.8X, Width %d\n", - ACPI_FORMAT_UINT64(*value), - obj_desc->common_field. - access_byte_width)); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Value Written %8.8X%8.8X, Width %d\n", - ACPI_FORMAT_UINT64(*value), - obj_desc->common_field. - access_byte_width)); - } - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_write_with_update_rule - * - * PARAMETERS: obj_desc - Field to be written - * Mask - bitmask within field datum - * field_value - Value to write - * field_datum_byte_offset - Offset of datum within field - * - * RETURN: Status - * - * DESCRIPTION: Apply the field update rule to a field write - * - ******************************************************************************/ - -acpi_status -acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, - acpi_integer mask, - acpi_integer field_value, - u32 field_datum_byte_offset) -{ - acpi_status status = AE_OK; - acpi_integer merged_value; - acpi_integer current_value; - - ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask); - - /* Start with the new bits */ - - merged_value = field_value; - - /* If the mask is all ones, we don't need to worry about the update rule */ - - if (mask != ACPI_INTEGER_MAX) { - - /* Decode the update rule */ - - switch (obj_desc->common_field. - field_flags & AML_FIELD_UPDATE_RULE_MASK) { - case AML_FIELD_UPDATE_PRESERVE: - /* - * Check if update rule needs to be applied (not if mask is all - * ones) The left shift drops the bits we want to ignore. - */ - if ((~mask << (ACPI_MUL_8(sizeof(mask)) - - ACPI_MUL_8(obj_desc->common_field. - access_byte_width))) != 0) { - /* - * Read the current contents of the byte/word/dword containing - * the field, and merge with the new field value. - */ - status = - acpi_ex_field_datum_io(obj_desc, - field_datum_byte_offset, - ¤t_value, - ACPI_READ); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - merged_value |= (current_value & ~mask); - } - break; - - case AML_FIELD_UPDATE_WRITE_AS_ONES: - - /* Set positions outside the field to all ones */ - - merged_value |= ~mask; - break; - - case AML_FIELD_UPDATE_WRITE_AS_ZEROS: - - /* Set positions outside the field to all zeros */ - - merged_value &= mask; - break; - - default: - - ACPI_ERROR((AE_INFO, - "Unknown UpdateRule value: %X", - (obj_desc->common_field. - field_flags & - AML_FIELD_UPDATE_RULE_MASK))); - return_ACPI_STATUS(AE_AML_OPERAND_VALUE); - } - } - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(mask), - field_datum_byte_offset, - obj_desc->common_field.access_byte_width, - ACPI_FORMAT_UINT64(field_value), - ACPI_FORMAT_UINT64(merged_value))); - - /* Write the merged value */ - - status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset, - &merged_value, ACPI_WRITE); - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_extract_from_field - * - * PARAMETERS: obj_desc - Field to be read - * Buffer - Where to store the field data - * buffer_length - Length of Buffer - * - * RETURN: Status - * - * DESCRIPTION: Retrieve the current value of the given field - * - ******************************************************************************/ - -acpi_status -acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, - void *buffer, u32 buffer_length) -{ - acpi_status status; - acpi_integer raw_datum; - acpi_integer merged_datum; - u32 field_offset = 0; - u32 buffer_offset = 0; - u32 buffer_tail_bits; - u32 datum_count; - u32 field_datum_count; - u32 i; - - ACPI_FUNCTION_TRACE(ex_extract_from_field); - - /* Validate target buffer and clear it */ - - if (buffer_length < - ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { - ACPI_ERROR((AE_INFO, - "Field size %X (bits) is too large for buffer (%X)", - obj_desc->common_field.bit_length, buffer_length)); - - return_ACPI_STATUS(AE_BUFFER_OVERFLOW); - } - ACPI_MEMSET(buffer, 0, buffer_length); - - /* Compute the number of datums (access width data items) */ - - datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, - obj_desc->common_field.access_bit_width); - field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + - obj_desc->common_field. - start_field_bit_offset, - obj_desc->common_field. - access_bit_width); - - /* Priming read from the field */ - - status = - acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum, - ACPI_READ); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - merged_datum = - raw_datum >> obj_desc->common_field.start_field_bit_offset; - - /* Read the rest of the field */ - - for (i = 1; i < field_datum_count; i++) { - - /* Get next input datum from the field */ - - field_offset += obj_desc->common_field.access_byte_width; - status = acpi_ex_field_datum_io(obj_desc, field_offset, - &raw_datum, ACPI_READ); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Merge with previous datum if necessary. - * - * Note: Before the shift, check if the shift value will be larger than - * the integer size. If so, there is no need to perform the operation. - * This avoids the differences in behavior between different compilers - * concerning shift values larger than the target data width. - */ - if ((obj_desc->common_field.access_bit_width - - obj_desc->common_field.start_field_bit_offset) < - ACPI_INTEGER_BIT_SIZE) { - merged_datum |= - raw_datum << (obj_desc->common_field. - access_bit_width - - obj_desc->common_field. - start_field_bit_offset); - } - - if (i == datum_count) { - break; - } - - /* Write merged datum to target buffer */ - - ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum, - ACPI_MIN(obj_desc->common_field.access_byte_width, - buffer_length - buffer_offset)); - - buffer_offset += obj_desc->common_field.access_byte_width; - merged_datum = - raw_datum >> obj_desc->common_field.start_field_bit_offset; - } - - /* Mask off any extra bits in the last datum */ - - buffer_tail_bits = obj_desc->common_field.bit_length % - obj_desc->common_field.access_bit_width; - if (buffer_tail_bits) { - merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); - } - - /* Write the last datum to the buffer */ - - ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum, - ACPI_MIN(obj_desc->common_field.access_byte_width, - buffer_length - buffer_offset)); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_insert_into_field - * - * PARAMETERS: obj_desc - Field to be written - * Buffer - Data to be written - * buffer_length - Length of Buffer - * - * RETURN: Status - * - * DESCRIPTION: Store the Buffer contents into the given field - * - ******************************************************************************/ - -acpi_status -acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, - void *buffer, u32 buffer_length) -{ - acpi_status status; - acpi_integer mask; - acpi_integer width_mask; - acpi_integer merged_datum; - acpi_integer raw_datum = 0; - u32 field_offset = 0; - u32 buffer_offset = 0; - u32 buffer_tail_bits; - u32 datum_count; - u32 field_datum_count; - u32 i; - u32 required_length; - void *new_buffer; - - ACPI_FUNCTION_TRACE(ex_insert_into_field); - - /* Validate input buffer */ - - new_buffer = NULL; - required_length = - ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); - /* - * We must have a buffer that is at least as long as the field - * we are writing to. This is because individual fields are - * indivisible and partial writes are not supported -- as per - * the ACPI specification. - */ - if (buffer_length < required_length) { - - /* We need to create a new buffer */ - - new_buffer = ACPI_ALLOCATE_ZEROED(required_length); - if (!new_buffer) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* - * Copy the original data to the new buffer, starting - * at Byte zero. All unused (upper) bytes of the - * buffer will be 0. - */ - ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); - buffer = new_buffer; - buffer_length = required_length; - } - - /* - * Create the bitmasks used for bit insertion. - * Note: This if/else is used to bypass compiler differences with the - * shift operator - */ - if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) { - width_mask = ACPI_INTEGER_MAX; - } else { - width_mask = - ACPI_MASK_BITS_ABOVE(obj_desc->common_field. - access_bit_width); - } - - mask = width_mask & - ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset); - - /* Compute the number of datums (access width data items) */ - - datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, - obj_desc->common_field.access_bit_width); - - field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + - obj_desc->common_field. - start_field_bit_offset, - obj_desc->common_field. - access_bit_width); - - /* Get initial Datum from the input buffer */ - - ACPI_MEMCPY(&raw_datum, buffer, - ACPI_MIN(obj_desc->common_field.access_byte_width, - buffer_length - buffer_offset)); - - merged_datum = - raw_datum << obj_desc->common_field.start_field_bit_offset; - - /* Write the entire field */ - - for (i = 1; i < field_datum_count; i++) { - - /* Write merged datum to the target field */ - - merged_datum &= mask; - status = acpi_ex_write_with_update_rule(obj_desc, mask, - merged_datum, - field_offset); - if (ACPI_FAILURE(status)) { - goto exit; - } - - field_offset += obj_desc->common_field.access_byte_width; - - /* - * Start new output datum by merging with previous input datum - * if necessary. - * - * Note: Before the shift, check if the shift value will be larger than - * the integer size. If so, there is no need to perform the operation. - * This avoids the differences in behavior between different compilers - * concerning shift values larger than the target data width. - */ - if ((obj_desc->common_field.access_bit_width - - obj_desc->common_field.start_field_bit_offset) < - ACPI_INTEGER_BIT_SIZE) { - merged_datum = - raw_datum >> (obj_desc->common_field. - access_bit_width - - obj_desc->common_field. - start_field_bit_offset); - } else { - merged_datum = 0; - } - - mask = width_mask; - - if (i == datum_count) { - break; - } - - /* Get the next input datum from the buffer */ - - buffer_offset += obj_desc->common_field.access_byte_width; - ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset, - ACPI_MIN(obj_desc->common_field.access_byte_width, - buffer_length - buffer_offset)); - merged_datum |= - raw_datum << obj_desc->common_field.start_field_bit_offset; - } - - /* Mask off any extra bits in the last datum */ - - buffer_tail_bits = (obj_desc->common_field.bit_length + - obj_desc->common_field.start_field_bit_offset) % - obj_desc->common_field.access_bit_width; - if (buffer_tail_bits) { - mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); - } - - /* Write the last datum to the field */ - - merged_datum &= mask; - status = acpi_ex_write_with_update_rule(obj_desc, - mask, merged_datum, - field_offset); - - exit: - /* Free temporary buffer if we used one */ - - if (new_buffer) { - ACPI_FREE(new_buffer); - } - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c deleted file mode 100644 index e445463de8a9..000000000000 --- a/drivers/acpi/executer/exmisc.c +++ /dev/null @@ -1,726 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exmisc") - -/******************************************************************************* - * - * FUNCTION: acpi_ex_get_object_reference - * - * PARAMETERS: obj_desc - Create a reference to this object - * return_desc - Where to store the reference - * walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Obtain and return a "reference" to the target object - * Common code for the ref_of_op and the cond_ref_of_op. - * - ******************************************************************************/ -acpi_status -acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, - union acpi_operand_object **return_desc, - struct acpi_walk_state *walk_state) -{ - union acpi_operand_object *reference_obj; - union acpi_operand_object *referenced_obj; - - ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc); - - *return_desc = NULL; - - switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { - case ACPI_DESC_TYPE_OPERAND: - - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) { - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* - * Must be a reference to a Local or Arg - */ - switch (obj_desc->reference.class) { - case ACPI_REFCLASS_LOCAL: - case ACPI_REFCLASS_ARG: - case ACPI_REFCLASS_DEBUG: - - /* The referenced object is the pseudo-node for the local/arg */ - - referenced_obj = obj_desc->reference.object; - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X", - obj_desc->reference.class)); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - break; - - case ACPI_DESC_TYPE_NAMED: - - /* - * A named reference that has already been resolved to a Node - */ - referenced_obj = obj_desc; - break; - - default: - - ACPI_ERROR((AE_INFO, "Invalid descriptor type %X", - ACPI_GET_DESCRIPTOR_TYPE(obj_desc))); - return_ACPI_STATUS(AE_TYPE); - } - - /* Create a new reference object */ - - reference_obj = - acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); - if (!reference_obj) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - reference_obj->reference.class = ACPI_REFCLASS_REFOF; - reference_obj->reference.object = referenced_obj; - *return_desc = reference_obj; - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Object %p Type [%s], returning Reference %p\n", - obj_desc, acpi_ut_get_object_type_name(obj_desc), - *return_desc)); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_concat_template - * - * PARAMETERS: Operand0 - First source object - * Operand1 - Second source object - * actual_return_desc - Where to place the return object - * walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Concatenate two resource templates - * - ******************************************************************************/ - -acpi_status -acpi_ex_concat_template(union acpi_operand_object *operand0, - union acpi_operand_object *operand1, - union acpi_operand_object **actual_return_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_operand_object *return_desc; - u8 *new_buf; - u8 *end_tag; - acpi_size length0; - acpi_size length1; - acpi_size new_length; - - ACPI_FUNCTION_TRACE(ex_concat_template); - - /* - * Find the end_tag descriptor in each resource template. - * Note1: returned pointers point TO the end_tag, not past it. - * Note2: zero-length buffers are allowed; treated like one end_tag - */ - - /* Get the length of the first resource template */ - - status = acpi_ut_get_resource_end_tag(operand0, &end_tag); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer); - - /* Get the length of the second resource template */ - - status = acpi_ut_get_resource_end_tag(operand1, &end_tag); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer); - - /* Combine both lengths, minimum size will be 2 for end_tag */ - - new_length = length0 + length1 + sizeof(struct aml_resource_end_tag); - - /* Create a new buffer object for the result (with one end_tag) */ - - return_desc = acpi_ut_create_buffer_object(new_length); - if (!return_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* - * Copy the templates to the new buffer, 0 first, then 1 follows. One - * end_tag descriptor is copied from Operand1. - */ - new_buf = return_desc->buffer.pointer; - ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length0); - ACPI_MEMCPY(new_buf + length0, operand1->buffer.pointer, length1); - - /* Insert end_tag and set the checksum to zero, means "ignore checksum" */ - - new_buf[new_length - 1] = 0; - new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1; - - /* Return the completed resource template */ - - *actual_return_desc = return_desc; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_do_concatenate - * - * PARAMETERS: Operand0 - First source object - * Operand1 - Second source object - * actual_return_desc - Where to place the return object - * walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. - * - ******************************************************************************/ - -acpi_status -acpi_ex_do_concatenate(union acpi_operand_object *operand0, - union acpi_operand_object *operand1, - union acpi_operand_object **actual_return_desc, - struct acpi_walk_state *walk_state) -{ - union acpi_operand_object *local_operand1 = operand1; - union acpi_operand_object *return_desc; - char *new_buf; - acpi_status status; - - ACPI_FUNCTION_TRACE(ex_do_concatenate); - - /* - * Convert the second operand if necessary. The first operand - * determines the type of the second operand, (See the Data Types - * section of the ACPI specification.) Both object types are - * guaranteed to be either Integer/String/Buffer by the operand - * resolution mechanism. - */ - switch (ACPI_GET_OBJECT_TYPE(operand0)) { - case ACPI_TYPE_INTEGER: - status = - acpi_ex_convert_to_integer(operand1, &local_operand1, 16); - break; - - case ACPI_TYPE_STRING: - status = acpi_ex_convert_to_string(operand1, &local_operand1, - ACPI_IMPLICIT_CONVERT_HEX); - break; - - case ACPI_TYPE_BUFFER: - status = acpi_ex_convert_to_buffer(operand1, &local_operand1); - break; - - default: - ACPI_ERROR((AE_INFO, "Invalid object type: %X", - ACPI_GET_OBJECT_TYPE(operand0))); - status = AE_AML_INTERNAL; - } - - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* - * Both operands are now known to be the same object type - * (Both are Integer, String, or Buffer), and we can now perform the - * concatenation. - */ - - /* - * There are three cases to handle: - * - * 1) Two Integers concatenated to produce a new Buffer - * 2) Two Strings concatenated to produce a new String - * 3) Two Buffers concatenated to produce a new Buffer - */ - switch (ACPI_GET_OBJECT_TYPE(operand0)) { - case ACPI_TYPE_INTEGER: - - /* Result of two Integers is a Buffer */ - /* Need enough buffer space for two integers */ - - return_desc = acpi_ut_create_buffer_object((acpi_size) - ACPI_MUL_2 - (acpi_gbl_integer_byte_width)); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - new_buf = (char *)return_desc->buffer.pointer; - - /* Copy the first integer, LSB first */ - - ACPI_MEMCPY(new_buf, &operand0->integer.value, - acpi_gbl_integer_byte_width); - - /* Copy the second integer (LSB first) after the first */ - - ACPI_MEMCPY(new_buf + acpi_gbl_integer_byte_width, - &local_operand1->integer.value, - acpi_gbl_integer_byte_width); - break; - - case ACPI_TYPE_STRING: - - /* Result of two Strings is a String */ - - return_desc = acpi_ut_create_string_object(((acpi_size) - operand0->string. - length + - local_operand1-> - string.length)); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - new_buf = return_desc->string.pointer; - - /* Concatenate the strings */ - - ACPI_STRCPY(new_buf, operand0->string.pointer); - ACPI_STRCPY(new_buf + operand0->string.length, - local_operand1->string.pointer); - break; - - case ACPI_TYPE_BUFFER: - - /* Result of two Buffers is a Buffer */ - - return_desc = acpi_ut_create_buffer_object(((acpi_size) - operand0->buffer. - length + - local_operand1-> - buffer.length)); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - new_buf = (char *)return_desc->buffer.pointer; - - /* Concatenate the buffers */ - - ACPI_MEMCPY(new_buf, operand0->buffer.pointer, - operand0->buffer.length); - ACPI_MEMCPY(new_buf + operand0->buffer.length, - local_operand1->buffer.pointer, - local_operand1->buffer.length); - break; - - default: - - /* Invalid object type, should not happen here */ - - ACPI_ERROR((AE_INFO, "Invalid object type: %X", - ACPI_GET_OBJECT_TYPE(operand0))); - status = AE_AML_INTERNAL; - goto cleanup; - } - - *actual_return_desc = return_desc; - - cleanup: - if (local_operand1 != operand1) { - acpi_ut_remove_reference(local_operand1); - } - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_do_math_op - * - * PARAMETERS: Opcode - AML opcode - * Integer0 - Integer operand #0 - * Integer1 - Integer operand #1 - * - * RETURN: Integer result of the operation - * - * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the - * math functions here is to prevent a lot of pointer dereferencing - * to obtain the operands. - * - ******************************************************************************/ - -acpi_integer -acpi_ex_do_math_op(u16 opcode, acpi_integer integer0, acpi_integer integer1) -{ - - ACPI_FUNCTION_ENTRY(); - - switch (opcode) { - case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ - - return (integer0 + integer1); - - case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ - - return (integer0 & integer1); - - case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ - - return (~(integer0 & integer1)); - - case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ - - return (integer0 | integer1); - - case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ - - return (~(integer0 | integer1)); - - case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ - - return (integer0 ^ integer1); - - case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ - - return (integer0 * integer1); - - case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */ - - /* - * We need to check if the shiftcount is larger than the integer bit - * width since the behavior of this is not well-defined in the C language. - */ - if (integer1 >= acpi_gbl_integer_bit_width) { - return (0); - } - return (integer0 << integer1); - - case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */ - - /* - * We need to check if the shiftcount is larger than the integer bit - * width since the behavior of this is not well-defined in the C language. - */ - if (integer1 >= acpi_gbl_integer_bit_width) { - return (0); - } - return (integer0 >> integer1); - - case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ - - return (integer0 - integer1); - - default: - - return (0); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_do_logical_numeric_op - * - * PARAMETERS: Opcode - AML opcode - * Integer0 - Integer operand #0 - * Integer1 - Integer operand #1 - * logical_result - TRUE/FALSE result of the operation - * - * RETURN: Status - * - * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric - * operators (LAnd and LOr), both operands must be integers. - * - * Note: cleanest machine code seems to be produced by the code - * below, rather than using statements of the form: - * Result = (Integer0 && Integer1); - * - ******************************************************************************/ - -acpi_status -acpi_ex_do_logical_numeric_op(u16 opcode, - acpi_integer integer0, - acpi_integer integer1, u8 * logical_result) -{ - acpi_status status = AE_OK; - u8 local_result = FALSE; - - ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op); - - switch (opcode) { - case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ - - if (integer0 && integer1) { - local_result = TRUE; - } - break; - - case AML_LOR_OP: /* LOr (Integer0, Integer1) */ - - if (integer0 || integer1) { - local_result = TRUE; - } - break; - - default: - status = AE_AML_INTERNAL; - break; - } - - /* Return the logical result and status */ - - *logical_result = local_result; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_do_logical_op - * - * PARAMETERS: Opcode - AML opcode - * Operand0 - operand #0 - * Operand1 - operand #1 - * logical_result - TRUE/FALSE result of the operation - * - * RETURN: Status - * - * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the - * functions here is to prevent a lot of pointer dereferencing - * to obtain the operands and to simplify the generation of the - * logical value. For the Numeric operators (LAnd and LOr), both - * operands must be integers. For the other logical operators, - * operands can be any combination of Integer/String/Buffer. The - * first operand determines the type to which the second operand - * will be converted. - * - * Note: cleanest machine code seems to be produced by the code - * below, rather than using statements of the form: - * Result = (Operand0 == Operand1); - * - ******************************************************************************/ - -acpi_status -acpi_ex_do_logical_op(u16 opcode, - union acpi_operand_object *operand0, - union acpi_operand_object *operand1, u8 * logical_result) -{ - union acpi_operand_object *local_operand1 = operand1; - acpi_integer integer0; - acpi_integer integer1; - u32 length0; - u32 length1; - acpi_status status = AE_OK; - u8 local_result = FALSE; - int compare; - - ACPI_FUNCTION_TRACE(ex_do_logical_op); - - /* - * Convert the second operand if necessary. The first operand - * determines the type of the second operand, (See the Data Types - * section of the ACPI 3.0+ specification.) Both object types are - * guaranteed to be either Integer/String/Buffer by the operand - * resolution mechanism. - */ - switch (ACPI_GET_OBJECT_TYPE(operand0)) { - case ACPI_TYPE_INTEGER: - status = - acpi_ex_convert_to_integer(operand1, &local_operand1, 16); - break; - - case ACPI_TYPE_STRING: - status = acpi_ex_convert_to_string(operand1, &local_operand1, - ACPI_IMPLICIT_CONVERT_HEX); - break; - - case ACPI_TYPE_BUFFER: - status = acpi_ex_convert_to_buffer(operand1, &local_operand1); - break; - - default: - status = AE_AML_INTERNAL; - break; - } - - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* - * Two cases: 1) Both Integers, 2) Both Strings or Buffers - */ - if (ACPI_GET_OBJECT_TYPE(operand0) == ACPI_TYPE_INTEGER) { - /* - * 1) Both operands are of type integer - * Note: local_operand1 may have changed above - */ - integer0 = operand0->integer.value; - integer1 = local_operand1->integer.value; - - switch (opcode) { - case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ - - if (integer0 == integer1) { - local_result = TRUE; - } - break; - - case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ - - if (integer0 > integer1) { - local_result = TRUE; - } - break; - - case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ - - if (integer0 < integer1) { - local_result = TRUE; - } - break; - - default: - status = AE_AML_INTERNAL; - break; - } - } else { - /* - * 2) Both operands are Strings or both are Buffers - * Note: Code below takes advantage of common Buffer/String - * object fields. local_operand1 may have changed above. Use - * memcmp to handle nulls in buffers. - */ - length0 = operand0->buffer.length; - length1 = local_operand1->buffer.length; - - /* Lexicographic compare: compare the data bytes */ - - compare = ACPI_MEMCMP(operand0->buffer.pointer, - local_operand1->buffer.pointer, - (length0 > length1) ? length1 : length0); - - switch (opcode) { - case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ - - /* Length and all bytes must be equal */ - - if ((length0 == length1) && (compare == 0)) { - - /* Length and all bytes match ==> TRUE */ - - local_result = TRUE; - } - break; - - case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ - - if (compare > 0) { - local_result = TRUE; - goto cleanup; /* TRUE */ - } - if (compare < 0) { - goto cleanup; /* FALSE */ - } - - /* Bytes match (to shortest length), compare lengths */ - - if (length0 > length1) { - local_result = TRUE; - } - break; - - case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ - - if (compare > 0) { - goto cleanup; /* FALSE */ - } - if (compare < 0) { - local_result = TRUE; - goto cleanup; /* TRUE */ - } - - /* Bytes match (to shortest length), compare lengths */ - - if (length0 < length1) { - local_result = TRUE; - } - break; - - default: - status = AE_AML_INTERNAL; - break; - } - } - - cleanup: - - /* New object was created if implicit conversion performed - delete */ - - if (local_operand1 != operand1) { - acpi_ut_remove_reference(local_operand1); - } - - /* Return the logical result and status */ - - *logical_result = local_result; - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c deleted file mode 100644 index f86bcee8d656..000000000000 --- a/drivers/acpi/executer/exmutex.c +++ /dev/null @@ -1,474 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exmutex - ASL Mutex Acquire/Release functions - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exmutex") - -/* Local prototypes */ -static void -acpi_ex_link_mutex(union acpi_operand_object *obj_desc, - struct acpi_thread_state *thread); - -/******************************************************************************* - * - * FUNCTION: acpi_ex_unlink_mutex - * - * PARAMETERS: obj_desc - The mutex to be unlinked - * - * RETURN: None - * - * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list - * - ******************************************************************************/ - -void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc) -{ - struct acpi_thread_state *thread = obj_desc->mutex.owner_thread; - - if (!thread) { - return; - } - - /* Doubly linked list */ - - if (obj_desc->mutex.next) { - (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev; - } - - if (obj_desc->mutex.prev) { - (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next; - } else { - thread->acquired_mutex_list = obj_desc->mutex.next; - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_link_mutex - * - * PARAMETERS: obj_desc - The mutex to be linked - * Thread - Current executing thread object - * - * RETURN: None - * - * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk - * - ******************************************************************************/ - -static void -acpi_ex_link_mutex(union acpi_operand_object *obj_desc, - struct acpi_thread_state *thread) -{ - union acpi_operand_object *list_head; - - list_head = thread->acquired_mutex_list; - - /* This object will be the first object in the list */ - - obj_desc->mutex.prev = NULL; - obj_desc->mutex.next = list_head; - - /* Update old first object to point back to this object */ - - if (list_head) { - list_head->mutex.prev = obj_desc; - } - - /* Update list head */ - - thread->acquired_mutex_list = obj_desc; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_acquire_mutex_object - * - * PARAMETERS: time_desc - Timeout in milliseconds - * obj_desc - Mutex object - * Thread - Current thread state - * - * RETURN: Status - * - * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common - * path that supports multiple acquires by the same thread. - * - * MUTEX: Interpreter must be locked - * - * NOTE: This interface is called from three places: - * 1) From acpi_ex_acquire_mutex, via an AML Acquire() operator - * 2) From acpi_ex_acquire_global_lock when an AML Field access requires the - * global lock - * 3) From the external interface, acpi_acquire_global_lock - * - ******************************************************************************/ - -acpi_status -acpi_ex_acquire_mutex_object(u16 timeout, - union acpi_operand_object *obj_desc, - acpi_thread_id thread_id) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc); - - if (!obj_desc) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Support for multiple acquires by the owning thread */ - - if (obj_desc->mutex.thread_id == thread_id) { - /* - * The mutex is already owned by this thread, just increment the - * acquisition depth - */ - obj_desc->mutex.acquisition_depth++; - return_ACPI_STATUS(AE_OK); - } - - /* Acquire the mutex, wait if necessary. Special case for Global Lock */ - - if (obj_desc == acpi_gbl_global_lock_mutex) { - status = acpi_ev_acquire_global_lock(timeout); - } else { - status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, - timeout); - } - - if (ACPI_FAILURE(status)) { - - /* Includes failure from a timeout on time_desc */ - - return_ACPI_STATUS(status); - } - - /* Acquired the mutex: update mutex object */ - - obj_desc->mutex.thread_id = thread_id; - obj_desc->mutex.acquisition_depth = 1; - obj_desc->mutex.original_sync_level = 0; - obj_desc->mutex.owner_thread = NULL; /* Used only for AML Acquire() */ - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_acquire_mutex - * - * PARAMETERS: time_desc - Timeout integer - * obj_desc - Mutex object - * walk_state - Current method execution state - * - * RETURN: Status - * - * DESCRIPTION: Acquire an AML mutex - * - ******************************************************************************/ - -acpi_status -acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, - union acpi_operand_object *obj_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex, obj_desc); - - if (!obj_desc) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Must have a valid thread ID */ - - if (!walk_state->thread) { - ACPI_ERROR((AE_INFO, - "Cannot acquire Mutex [%4.4s], null thread info", - acpi_ut_get_node_name(obj_desc->mutex.node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - /* - * Current sync level must be less than or equal to the sync level of the - * mutex. This mechanism provides some deadlock prevention - */ - if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { - ACPI_ERROR((AE_INFO, - "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%d)", - acpi_ut_get_node_name(obj_desc->mutex.node), - walk_state->thread->current_sync_level)); - return_ACPI_STATUS(AE_AML_MUTEX_ORDER); - } - - status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value, - obj_desc, - walk_state->thread->thread_id); - if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) { - - /* Save Thread object, original/current sync levels */ - - obj_desc->mutex.owner_thread = walk_state->thread; - obj_desc->mutex.original_sync_level = - walk_state->thread->current_sync_level; - walk_state->thread->current_sync_level = - obj_desc->mutex.sync_level; - - /* Link the mutex to the current thread for force-unlock at method exit */ - - acpi_ex_link_mutex(obj_desc, walk_state->thread); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_release_mutex_object - * - * PARAMETERS: obj_desc - The object descriptor for this op - * - * RETURN: Status - * - * DESCRIPTION: Release a previously acquired Mutex, low level interface. - * Provides a common path that supports multiple releases (after - * previous multiple acquires) by the same thread. - * - * MUTEX: Interpreter must be locked - * - * NOTE: This interface is called from three places: - * 1) From acpi_ex_release_mutex, via an AML Acquire() operator - * 2) From acpi_ex_release_global_lock when an AML Field access requires the - * global lock - * 3) From the external interface, acpi_release_global_lock - * - ******************************************************************************/ - -acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ex_release_mutex_object); - - if (obj_desc->mutex.acquisition_depth == 0) { - return (AE_NOT_ACQUIRED); - } - - /* Match multiple Acquires with multiple Releases */ - - obj_desc->mutex.acquisition_depth--; - if (obj_desc->mutex.acquisition_depth != 0) { - - /* Just decrement the depth and return */ - - return_ACPI_STATUS(AE_OK); - } - - if (obj_desc->mutex.owner_thread) { - - /* Unlink the mutex from the owner's list */ - - acpi_ex_unlink_mutex(obj_desc); - obj_desc->mutex.owner_thread = NULL; - } - - /* Release the mutex, special case for Global Lock */ - - if (obj_desc == acpi_gbl_global_lock_mutex) { - status = acpi_ev_release_global_lock(); - } else { - acpi_os_release_mutex(obj_desc->mutex.os_mutex); - } - - /* Clear mutex info */ - - obj_desc->mutex.thread_id = NULL; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_release_mutex - * - * PARAMETERS: obj_desc - The object descriptor for this op - * walk_state - Current method execution state - * - * RETURN: Status - * - * DESCRIPTION: Release a previously acquired Mutex. - * - ******************************************************************************/ - -acpi_status -acpi_ex_release_mutex(union acpi_operand_object *obj_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ex_release_mutex); - - if (!obj_desc) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* The mutex must have been previously acquired in order to release it */ - - if (!obj_desc->mutex.owner_thread) { - ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], not acquired", - acpi_ut_get_node_name(obj_desc->mutex.node))); - return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); - } - - /* - * The Mutex is owned, but this thread must be the owner. - * Special case for Global Lock, any thread can release - */ - if ((obj_desc->mutex.owner_thread->thread_id != - walk_state->thread->thread_id) - && (obj_desc != acpi_gbl_global_lock_mutex)) { - ACPI_ERROR((AE_INFO, - "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", - (unsigned long)walk_state->thread->thread_id, - acpi_ut_get_node_name(obj_desc->mutex.node), - (unsigned long)obj_desc->mutex.owner_thread-> - thread_id)); - return_ACPI_STATUS(AE_AML_NOT_OWNER); - } - - /* Must have a valid thread ID */ - - if (!walk_state->thread) { - ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], null thread info", - acpi_ut_get_node_name(obj_desc->mutex.node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - /* - * The sync level of the mutex must be less than or equal to the current - * sync level - */ - if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { - ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %d current %d", - acpi_ut_get_node_name(obj_desc->mutex.node), - obj_desc->mutex.sync_level, - walk_state->thread->current_sync_level)); - return_ACPI_STATUS(AE_AML_MUTEX_ORDER); - } - - status = acpi_ex_release_mutex_object(obj_desc); - - if (obj_desc->mutex.acquisition_depth == 0) { - - /* Restore the original sync_level */ - - walk_state->thread->current_sync_level = - obj_desc->mutex.original_sync_level; - } - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_release_all_mutexes - * - * PARAMETERS: Thread - Current executing thread object - * - * RETURN: Status - * - * DESCRIPTION: Release all mutexes held by this thread - * - * NOTE: This function is called as the thread is exiting the interpreter. - * Mutexes are not released when an individual control method is exited, but - * only when the parent thread actually exits the interpreter. This allows one - * method to acquire a mutex, and a different method to release it, as long as - * this is performed underneath a single parent control method. - * - ******************************************************************************/ - -void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) -{ - union acpi_operand_object *next = thread->acquired_mutex_list; - union acpi_operand_object *obj_desc; - - ACPI_FUNCTION_ENTRY(); - - /* Traverse the list of owned mutexes, releasing each one */ - - while (next) { - obj_desc = next; - next = obj_desc->mutex.next; - - obj_desc->mutex.prev = NULL; - obj_desc->mutex.next = NULL; - obj_desc->mutex.acquisition_depth = 0; - - /* Release the mutex, special case for Global Lock */ - - if (obj_desc == acpi_gbl_global_lock_mutex) { - - /* Ignore errors */ - - (void)acpi_ev_release_global_lock(); - } else { - acpi_os_release_mutex(obj_desc->mutex.os_mutex); - } - - /* Mark mutex unowned */ - - obj_desc->mutex.owner_thread = NULL; - obj_desc->mutex.thread_id = NULL; - - /* Update Thread sync_level (Last mutex is the important one) */ - - thread->current_sync_level = - obj_desc->mutex.original_sync_level; - } -} diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c deleted file mode 100644 index 12d3513531e1..000000000000 --- a/drivers/acpi/executer/exnames.c +++ /dev/null @@ -1,436 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exnames - interpreter/scanner name load/execute - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exnames") - -/* Local prototypes */ -static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs); - -static acpi_status -acpi_ex_name_segment(u8 ** in_aml_address, char *name_string); - -/******************************************************************************* - * - * FUNCTION: acpi_ex_allocate_name_string - * - * PARAMETERS: prefix_count - Count of parent levels. Special cases: - * (-1)==root, 0==none - * num_name_segs - count of 4-character name segments - * - * RETURN: A pointer to the allocated string segment. This segment must - * be deleted by the caller. - * - * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name - * string is long enough, and set up prefix if any. - * - ******************************************************************************/ - -static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs) -{ - char *temp_ptr; - char *name_string; - u32 size_needed; - - ACPI_FUNCTION_TRACE(ex_allocate_name_string); - - /* - * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix. - * Also, one byte for the null terminator. - * This may actually be somewhat longer than needed. - */ - if (prefix_count == ACPI_UINT32_MAX) { - - /* Special case for root */ - - size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; - } else { - size_needed = - prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; - } - - /* - * Allocate a buffer for the name. - * This buffer must be deleted by the caller! - */ - name_string = ACPI_ALLOCATE(size_needed); - if (!name_string) { - ACPI_ERROR((AE_INFO, - "Could not allocate size %d", size_needed)); - return_PTR(NULL); - } - - temp_ptr = name_string; - - /* Set up Root or Parent prefixes if needed */ - - if (prefix_count == ACPI_UINT32_MAX) { - *temp_ptr++ = AML_ROOT_PREFIX; - } else { - while (prefix_count--) { - *temp_ptr++ = AML_PARENT_PREFIX; - } - } - - /* Set up Dual or Multi prefixes if needed */ - - if (num_name_segs > 2) { - - /* Set up multi prefixes */ - - *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; - *temp_ptr++ = (char)num_name_segs; - } else if (2 == num_name_segs) { - - /* Set up dual prefixes */ - - *temp_ptr++ = AML_DUAL_NAME_PREFIX; - } - - /* - * Terminate string following prefixes. acpi_ex_name_segment() will - * append the segment(s) - */ - *temp_ptr = 0; - - return_PTR(name_string); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_name_segment - * - * PARAMETERS: in_aml_address - Pointer to the name in the AML code - * name_string - Where to return the name. The name is appended - * to any existing string to form a namepath - * - * RETURN: Status - * - * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream - * - ******************************************************************************/ - -static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) -{ - char *aml_address = (void *)*in_aml_address; - acpi_status status = AE_OK; - u32 index; - char char_buf[5]; - - ACPI_FUNCTION_TRACE(ex_name_segment); - - /* - * If first character is a digit, then we know that we aren't looking at a - * valid name segment - */ - char_buf[0] = *aml_address; - - if ('0' <= char_buf[0] && char_buf[0] <= '9') { - ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0])); - return_ACPI_STATUS(AE_CTRL_PENDING); - } - - ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n")); - - for (index = 0; (index < ACPI_NAME_SIZE) - && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) { - char_buf[index] = *aml_address++; - ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index])); - } - - /* Valid name segment */ - - if (index == 4) { - - /* Found 4 valid characters */ - - char_buf[4] = '\0'; - - if (name_string) { - ACPI_STRCAT(name_string, char_buf); - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Appended to - %s\n", name_string)); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "No Name string - %s\n", char_buf)); - } - } else if (index == 0) { - /* - * First character was not a valid name character, - * so we are looking at something other than a name. - */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Leading character is not alpha: %02Xh (not a name)\n", - char_buf[0])); - status = AE_CTRL_PENDING; - } else { - /* - * Segment started with one or more valid characters, but fewer than - * the required 4 - */ - status = AE_AML_BAD_NAME; - ACPI_ERROR((AE_INFO, - "Bad character %02x in name, at %p", - *aml_address, aml_address)); - } - - *in_aml_address = ACPI_CAST_PTR(u8, aml_address); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_get_name_string - * - * PARAMETERS: data_type - Object type to be associated with this - * name - * in_aml_address - Pointer to the namestring in the AML code - * out_name_string - Where the namestring is returned - * out_name_length - Length of the returned string - * - * RETURN: Status, namestring and length - * - * DESCRIPTION: Extract a full namepath from the AML byte stream, - * including any prefixes. - * - ******************************************************************************/ - -acpi_status -acpi_ex_get_name_string(acpi_object_type data_type, - u8 * in_aml_address, - char **out_name_string, u32 * out_name_length) -{ - acpi_status status = AE_OK; - u8 *aml_address = in_aml_address; - char *name_string = NULL; - u32 num_segments; - u32 prefix_count = 0; - u8 has_prefix = FALSE; - - ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address); - - if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type || - ACPI_TYPE_LOCAL_BANK_FIELD == data_type || - ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) { - - /* Disallow prefixes for types associated with field_unit names */ - - name_string = acpi_ex_allocate_name_string(0, 1); - if (!name_string) { - status = AE_NO_MEMORY; - } else { - status = - acpi_ex_name_segment(&aml_address, name_string); - } - } else { - /* - * data_type is not a field name. - * Examine first character of name for root or parent prefix operators - */ - switch (*aml_address) { - case AML_ROOT_PREFIX: - - ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "RootPrefix(\\) at %p\n", - aml_address)); - - /* - * Remember that we have a root_prefix -- - * see comment in acpi_ex_allocate_name_string() - */ - aml_address++; - prefix_count = ACPI_UINT32_MAX; - has_prefix = TRUE; - break; - - case AML_PARENT_PREFIX: - - /* Increment past possibly multiple parent prefixes */ - - do { - ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "ParentPrefix (^) at %p\n", - aml_address)); - - aml_address++; - prefix_count++; - - } while (*aml_address == AML_PARENT_PREFIX); - - has_prefix = TRUE; - break; - - default: - - /* Not a prefix character */ - - break; - } - - /* Examine first character of name for name segment prefix operator */ - - switch (*aml_address) { - case AML_DUAL_NAME_PREFIX: - - ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "DualNamePrefix at %p\n", - aml_address)); - - aml_address++; - name_string = - acpi_ex_allocate_name_string(prefix_count, 2); - if (!name_string) { - status = AE_NO_MEMORY; - break; - } - - /* Indicate that we processed a prefix */ - - has_prefix = TRUE; - - status = - acpi_ex_name_segment(&aml_address, name_string); - if (ACPI_SUCCESS(status)) { - status = - acpi_ex_name_segment(&aml_address, - name_string); - } - break; - - case AML_MULTI_NAME_PREFIX_OP: - - ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "MultiNamePrefix at %p\n", - aml_address)); - - /* Fetch count of segments remaining in name path */ - - aml_address++; - num_segments = *aml_address; - - name_string = - acpi_ex_allocate_name_string(prefix_count, - num_segments); - if (!name_string) { - status = AE_NO_MEMORY; - break; - } - - /* Indicate that we processed a prefix */ - - aml_address++; - has_prefix = TRUE; - - while (num_segments && - (status = - acpi_ex_name_segment(&aml_address, - name_string)) == AE_OK) { - num_segments--; - } - - break; - - case 0: - - /* null_name valid as of 8-12-98 ASL/AML Grammar Update */ - - if (prefix_count == ACPI_UINT32_MAX) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "NameSeg is \"\\\" followed by NULL\n")); - } - - /* Consume the NULL byte */ - - aml_address++; - name_string = - acpi_ex_allocate_name_string(prefix_count, 0); - if (!name_string) { - status = AE_NO_MEMORY; - break; - } - - break; - - default: - - /* Name segment string */ - - name_string = - acpi_ex_allocate_name_string(prefix_count, 1); - if (!name_string) { - status = AE_NO_MEMORY; - break; - } - - status = - acpi_ex_name_segment(&aml_address, name_string); - break; - } - } - - if (AE_CTRL_PENDING == status && has_prefix) { - - /* Ran out of segments after processing a prefix */ - - ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string)); - status = AE_AML_BAD_NAME; - } - - if (ACPI_FAILURE(status)) { - if (name_string) { - ACPI_FREE(name_string); - } - return_ACPI_STATUS(status); - } - - *out_name_string = name_string; - *out_name_length = (u32) (aml_address - in_aml_address); - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c deleted file mode 100644 index 52d78b8622be..000000000000 --- a/drivers/acpi/executer/exoparg1.c +++ /dev/null @@ -1,1050 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exoparg1 - AML execution - opcodes with 1 argument - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exoparg1") - -/*! - * Naming convention for AML interpreter execution routines. - * - * The routines that begin execution of AML opcodes are named with a common - * convention based upon the number of arguments, the number of target operands, - * and whether or not a value is returned: - * - * AcpiExOpcode_xA_yT_zR - * - * Where: - * - * xA - ARGUMENTS: The number of arguments (input operands) that are - * required for this opcode type (0 through 6 args). - * yT - TARGETS: The number of targets (output operands) that are required - * for this opcode type (0, 1, or 2 targets). - * zR - RETURN VALUE: Indicates whether this opcode type returns a value - * as the function return (0 or 1). - * - * The AcpiExOpcode* functions are called via the Dispatcher component with - * fully resolved operands. -!*/ -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_0A_0T_1R - * - * PARAMETERS: walk_state - Current state (contains AML opcode) - * - * RETURN: Status - * - * DESCRIPTION: Execute operator with no operands, one return value - * - ******************************************************************************/ -acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - union acpi_operand_object *return_desc = NULL; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_0A_0T_1R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - /* Examine the AML opcode */ - - switch (walk_state->opcode) { - case AML_TIMER_OP: /* Timer () */ - - /* Create a return object of type Integer */ - - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - return_desc->integer.value = acpi_os_get_timer(); - break; - - default: /* Unknown opcode */ - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - break; - } - - cleanup: - - /* Delete return object on error */ - - if ((ACPI_FAILURE(status)) || walk_state->result_obj) { - acpi_ut_remove_reference(return_desc); - walk_state->result_obj = NULL; - } else { - /* Save the return value */ - - walk_state->result_obj = return_desc; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_1A_0T_0R - * - * PARAMETERS: walk_state - Current state (contains AML opcode) - * - * RETURN: Status - * - * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on - * object stack - * - ******************************************************************************/ - -acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_0R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - /* Examine the AML opcode */ - - switch (walk_state->opcode) { - case AML_RELEASE_OP: /* Release (mutex_object) */ - - status = acpi_ex_release_mutex(operand[0], walk_state); - break; - - case AML_RESET_OP: /* Reset (event_object) */ - - status = acpi_ex_system_reset_event(operand[0]); - break; - - case AML_SIGNAL_OP: /* Signal (event_object) */ - - status = acpi_ex_system_signal_event(operand[0]); - break; - - case AML_SLEEP_OP: /* Sleep (msec_time) */ - - status = acpi_ex_system_do_suspend(operand[0]->integer.value); - break; - - case AML_STALL_OP: /* Stall (usec_time) */ - - status = - acpi_ex_system_do_stall((u32) operand[0]->integer.value); - break; - - case AML_UNLOAD_OP: /* Unload (Handle) */ - - status = acpi_ex_unload_table(operand[0]); - break; - - default: /* Unknown opcode */ - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - break; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_1A_1T_0R - * - * PARAMETERS: walk_state - Current state (contains AML opcode) - * - * RETURN: Status - * - * DESCRIPTION: Execute opcode with one argument, one target, and no - * return value. - * - ******************************************************************************/ - -acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - union acpi_operand_object **operand = &walk_state->operands[0]; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_0R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - /* Examine the AML opcode */ - - switch (walk_state->opcode) { - case AML_LOAD_OP: - - status = acpi_ex_load_op(operand[0], operand[1], walk_state); - break; - - default: /* Unknown opcode */ - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - cleanup: - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_1A_1T_1R - * - * PARAMETERS: walk_state - Current state (contains AML opcode) - * - * RETURN: Status - * - * DESCRIPTION: Execute opcode with one argument, one target, and a - * return value. - * - ******************************************************************************/ - -acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *return_desc = NULL; - union acpi_operand_object *return_desc2 = NULL; - u32 temp32; - u32 i; - acpi_integer power_of_ten; - acpi_integer digit; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_1R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - /* Examine the AML opcode */ - - switch (walk_state->opcode) { - case AML_BIT_NOT_OP: - case AML_FIND_SET_LEFT_BIT_OP: - case AML_FIND_SET_RIGHT_BIT_OP: - case AML_FROM_BCD_OP: - case AML_TO_BCD_OP: - case AML_COND_REF_OF_OP: - - /* Create a return object of type Integer for these opcodes */ - - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - switch (walk_state->opcode) { - case AML_BIT_NOT_OP: /* Not (Operand, Result) */ - - return_desc->integer.value = ~operand[0]->integer.value; - break; - - case AML_FIND_SET_LEFT_BIT_OP: /* find_set_left_bit (Operand, Result) */ - - return_desc->integer.value = operand[0]->integer.value; - - /* - * Acpi specification describes Integer type as a little - * endian unsigned value, so this boundary condition is valid. - */ - for (temp32 = 0; return_desc->integer.value && - temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { - return_desc->integer.value >>= 1; - } - - return_desc->integer.value = temp32; - break; - - case AML_FIND_SET_RIGHT_BIT_OP: /* find_set_right_bit (Operand, Result) */ - - return_desc->integer.value = operand[0]->integer.value; - - /* - * The Acpi specification describes Integer type as a little - * endian unsigned value, so this boundary condition is valid. - */ - for (temp32 = 0; return_desc->integer.value && - temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { - return_desc->integer.value <<= 1; - } - - /* Since the bit position is one-based, subtract from 33 (65) */ - - return_desc->integer.value = - temp32 == - 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32; - break; - - case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */ - - /* - * The 64-bit ACPI integer can hold 16 4-bit BCD characters - * (if table is 32-bit, integer can hold 8 BCD characters) - * Convert each 4-bit BCD value - */ - power_of_ten = 1; - return_desc->integer.value = 0; - digit = operand[0]->integer.value; - - /* Convert each BCD digit (each is one nybble wide) */ - - for (i = 0; - (i < acpi_gbl_integer_nybble_width) && (digit > 0); - i++) { - - /* Get the least significant 4-bit BCD digit */ - - temp32 = ((u32) digit) & 0xF; - - /* Check the range of the digit */ - - if (temp32 > 9) { - ACPI_ERROR((AE_INFO, - "BCD digit too large (not decimal): 0x%X", - temp32)); - - status = AE_AML_NUMERIC_OVERFLOW; - goto cleanup; - } - - /* Sum the digit into the result with the current power of 10 */ - - return_desc->integer.value += - (((acpi_integer) temp32) * power_of_ten); - - /* Shift to next BCD digit */ - - digit >>= 4; - - /* Next power of 10 */ - - power_of_ten *= 10; - } - break; - - case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */ - - return_desc->integer.value = 0; - digit = operand[0]->integer.value; - - /* Each BCD digit is one nybble wide */ - - for (i = 0; - (i < acpi_gbl_integer_nybble_width) && (digit > 0); - i++) { - (void)acpi_ut_short_divide(digit, 10, &digit, - &temp32); - - /* - * Insert the BCD digit that resides in the - * remainder from above - */ - return_desc->integer.value |= - (((acpi_integer) temp32) << ACPI_MUL_4(i)); - } - - /* Overflow if there is any data left in Digit */ - - if (digit > 0) { - ACPI_ERROR((AE_INFO, - "Integer too large to convert to BCD: %8.8X%8.8X", - ACPI_FORMAT_UINT64(operand[0]-> - integer.value))); - status = AE_AML_NUMERIC_OVERFLOW; - goto cleanup; - } - break; - - case AML_COND_REF_OF_OP: /* cond_ref_of (source_object, Result) */ - - /* - * This op is a little strange because the internal return value is - * different than the return value stored in the result descriptor - * (There are really two return values) - */ - if ((struct acpi_namespace_node *)operand[0] == - acpi_gbl_root_node) { - /* - * This means that the object does not exist in the namespace, - * return FALSE - */ - return_desc->integer.value = 0; - goto cleanup; - } - - /* Get the object reference, store it, and remove our reference */ - - status = acpi_ex_get_object_reference(operand[0], - &return_desc2, - walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - status = - acpi_ex_store(return_desc2, operand[1], walk_state); - acpi_ut_remove_reference(return_desc2); - - /* The object exists in the namespace, return TRUE */ - - return_desc->integer.value = ACPI_INTEGER_MAX; - goto cleanup; - - default: - /* No other opcodes get here */ - break; - } - break; - - case AML_STORE_OP: /* Store (Source, Target) */ - - /* - * A store operand is typically a number, string, buffer or lvalue - * Be careful about deleting the source object, - * since the object itself may have been stored. - */ - status = acpi_ex_store(operand[0], operand[1], walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* It is possible that the Store already produced a return object */ - - if (!walk_state->result_obj) { - /* - * Normally, we would remove a reference on the Operand[0] - * parameter; But since it is being used as the internal return - * object (meaning we would normally increment it), the two - * cancel out, and we simply don't do anything. - */ - walk_state->result_obj = operand[0]; - walk_state->operands[0] = NULL; /* Prevent deletion */ - } - return_ACPI_STATUS(status); - - /* - * ACPI 2.0 Opcodes - */ - case AML_COPY_OP: /* Copy (Source, Target) */ - - status = - acpi_ut_copy_iobject_to_iobject(operand[0], &return_desc, - walk_state); - break; - - case AML_TO_DECSTRING_OP: /* to_decimal_string (Data, Result) */ - - status = acpi_ex_convert_to_string(operand[0], &return_desc, - ACPI_EXPLICIT_CONVERT_DECIMAL); - if (return_desc == operand[0]) { - - /* No conversion performed, add ref to handle return value */ - acpi_ut_add_reference(return_desc); - } - break; - - case AML_TO_HEXSTRING_OP: /* to_hex_string (Data, Result) */ - - status = acpi_ex_convert_to_string(operand[0], &return_desc, - ACPI_EXPLICIT_CONVERT_HEX); - if (return_desc == operand[0]) { - - /* No conversion performed, add ref to handle return value */ - acpi_ut_add_reference(return_desc); - } - break; - - case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */ - - status = acpi_ex_convert_to_buffer(operand[0], &return_desc); - if (return_desc == operand[0]) { - - /* No conversion performed, add ref to handle return value */ - acpi_ut_add_reference(return_desc); - } - break; - - case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */ - - status = acpi_ex_convert_to_integer(operand[0], &return_desc, - ACPI_ANY_BASE); - if (return_desc == operand[0]) { - - /* No conversion performed, add ref to handle return value */ - acpi_ut_add_reference(return_desc); - } - break; - - case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */ - case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */ - - /* These are two obsolete opcodes */ - - ACPI_ERROR((AE_INFO, - "%s is obsolete and not implemented", - acpi_ps_get_opcode_name(walk_state->opcode))); - status = AE_SUPPORT; - goto cleanup; - - default: /* Unknown opcode */ - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - if (ACPI_SUCCESS(status)) { - - /* Store the return value computed above into the target object */ - - status = acpi_ex_store(return_desc, operand[1], walk_state); - } - - cleanup: - - /* Delete return object on error */ - - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(return_desc); - } - - /* Save return object on success */ - - else if (!walk_state->result_obj) { - walk_state->result_obj = return_desc; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_1A_0T_1R - * - * PARAMETERS: walk_state - Current state (contains AML opcode) - * - * RETURN: Status - * - * DESCRIPTION: Execute opcode with one argument, no target, and a return value - * - ******************************************************************************/ - -acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *temp_desc; - union acpi_operand_object *return_desc = NULL; - acpi_status status = AE_OK; - u32 type; - acpi_integer value; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_1R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - /* Examine the AML opcode */ - - switch (walk_state->opcode) { - case AML_LNOT_OP: /* LNot (Operand) */ - - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * Set result to ONES (TRUE) if Value == 0. Note: - * return_desc->Integer.Value is initially == 0 (FALSE) from above. - */ - if (!operand[0]->integer.value) { - return_desc->integer.value = ACPI_INTEGER_MAX; - } - break; - - case AML_DECREMENT_OP: /* Decrement (Operand) */ - case AML_INCREMENT_OP: /* Increment (Operand) */ - - /* - * Create a new integer. Can't just get the base integer and - * increment it because it may be an Arg or Field. - */ - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * Since we are expecting a Reference operand, it can be either a - * NS Node or an internal object. - */ - temp_desc = operand[0]; - if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) == - ACPI_DESC_TYPE_OPERAND) { - - /* Internal reference object - prevent deletion */ - - acpi_ut_add_reference(temp_desc); - } - - /* - * Convert the Reference operand to an Integer (This removes a - * reference on the Operand[0] object) - * - * NOTE: We use LNOT_OP here in order to force resolution of the - * reference operand to an actual integer. - */ - status = - acpi_ex_resolve_operands(AML_LNOT_OP, &temp_desc, - walk_state); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "While resolving operands for [%s]", - acpi_ps_get_opcode_name(walk_state-> - opcode))); - - goto cleanup; - } - - /* - * temp_desc is now guaranteed to be an Integer object -- - * Perform the actual increment or decrement - */ - if (walk_state->opcode == AML_INCREMENT_OP) { - return_desc->integer.value = - temp_desc->integer.value + 1; - } else { - return_desc->integer.value = - temp_desc->integer.value - 1; - } - - /* Finished with this Integer object */ - - acpi_ut_remove_reference(temp_desc); - - /* - * Store the result back (indirectly) through the original - * Reference object - */ - status = acpi_ex_store(return_desc, operand[0], walk_state); - break; - - case AML_TYPE_OP: /* object_type (source_object) */ - - /* - * Note: The operand is not resolved at this point because we want to - * get the associated object, not its value. For example, we don't - * want to resolve a field_unit to its value, we want the actual - * field_unit object. - */ - - /* Get the type of the base object */ - - status = - acpi_ex_resolve_multiple(walk_state, operand[0], &type, - NULL); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Allocate a descriptor to hold the type. */ - - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - return_desc->integer.value = type; - break; - - case AML_SIZE_OF_OP: /* size_of (source_object) */ - - /* - * Note: The operand is not resolved at this point because we want to - * get the associated object, not its value. - */ - - /* Get the base object */ - - status = acpi_ex_resolve_multiple(walk_state, - operand[0], &type, - &temp_desc); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* - * The type of the base object must be integer, buffer, string, or - * package. All others are not supported. - * - * NOTE: Integer is not specifically supported by the ACPI spec, - * but is supported implicitly via implicit operand conversion. - * rather than bother with conversion, we just use the byte width - * global (4 or 8 bytes). - */ - switch (type) { - case ACPI_TYPE_INTEGER: - value = acpi_gbl_integer_byte_width; - break; - - case ACPI_TYPE_STRING: - value = temp_desc->string.length; - break; - - case ACPI_TYPE_BUFFER: - - /* Buffer arguments may not be evaluated at this point */ - - status = acpi_ds_get_buffer_arguments(temp_desc); - value = temp_desc->buffer.length; - break; - - case ACPI_TYPE_PACKAGE: - - /* Package arguments may not be evaluated at this point */ - - status = acpi_ds_get_package_arguments(temp_desc); - value = temp_desc->package.count; - break; - - default: - ACPI_ERROR((AE_INFO, - "Operand must be Buffer/Integer/String/Package - found type %s", - acpi_ut_get_type_name(type))); - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* - * Now that we have the size of the object, create a result - * object to hold the value - */ - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - return_desc->integer.value = value; - break; - - case AML_REF_OF_OP: /* ref_of (source_object) */ - - status = - acpi_ex_get_object_reference(operand[0], &return_desc, - walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - break; - - case AML_DEREF_OF_OP: /* deref_of (obj_reference | String) */ - - /* Check for a method local or argument, or standalone String */ - - if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) == - ACPI_DESC_TYPE_NAMED) { - temp_desc = - acpi_ns_get_attached_object((struct - acpi_namespace_node *) - operand[0]); - if (temp_desc - && - ((ACPI_GET_OBJECT_TYPE(temp_desc) == - ACPI_TYPE_STRING) - || (ACPI_GET_OBJECT_TYPE(temp_desc) == - ACPI_TYPE_LOCAL_REFERENCE))) { - operand[0] = temp_desc; - acpi_ut_add_reference(temp_desc); - } else { - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - } else { - switch (ACPI_GET_OBJECT_TYPE(operand[0])) { - case ACPI_TYPE_LOCAL_REFERENCE: - /* - * This is a deref_of (local_x | arg_x) - * - * Must resolve/dereference the local/arg reference first - */ - switch (operand[0]->reference.class) { - case ACPI_REFCLASS_LOCAL: - case ACPI_REFCLASS_ARG: - - /* Set Operand[0] to the value of the local/arg */ - - status = - acpi_ds_method_data_get_value - (operand[0]->reference.class, - operand[0]->reference.value, - walk_state, &temp_desc); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* - * Delete our reference to the input object and - * point to the object just retrieved - */ - acpi_ut_remove_reference(operand[0]); - operand[0] = temp_desc; - break; - - case ACPI_REFCLASS_REFOF: - - /* Get the object to which the reference refers */ - - temp_desc = - operand[0]->reference.object; - acpi_ut_remove_reference(operand[0]); - operand[0] = temp_desc; - break; - - default: - - /* Must be an Index op - handled below */ - break; - } - break; - - case ACPI_TYPE_STRING: - break; - - default: - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - } - - if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) != - ACPI_DESC_TYPE_NAMED) { - if (ACPI_GET_OBJECT_TYPE(operand[0]) == - ACPI_TYPE_STRING) { - /* - * This is a deref_of (String). The string is a reference - * to a named ACPI object. - * - * 1) Find the owning Node - * 2) Dereference the node to an actual object. Could be a - * Field, so we need to resolve the node to a value. - */ - status = - acpi_ns_get_node(walk_state->scope_info-> - scope.node, - operand[0]->string.pointer, - ACPI_NS_SEARCH_PARENT, - ACPI_CAST_INDIRECT_PTR - (struct - acpi_namespace_node, - &return_desc)); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - status = - acpi_ex_resolve_node_to_value - (ACPI_CAST_INDIRECT_PTR - (struct acpi_namespace_node, &return_desc), - walk_state); - goto cleanup; - } - } - - /* Operand[0] may have changed from the code above */ - - if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) == - ACPI_DESC_TYPE_NAMED) { - /* - * This is a deref_of (object_reference) - * Get the actual object from the Node (This is the dereference). - * This case may only happen when a local_x or arg_x is - * dereferenced above. - */ - return_desc = acpi_ns_get_attached_object((struct - acpi_namespace_node - *) - operand[0]); - acpi_ut_add_reference(return_desc); - } else { - /* - * This must be a reference object produced by either the - * Index() or ref_of() operator - */ - switch (operand[0]->reference.class) { - case ACPI_REFCLASS_INDEX: - - /* - * The target type for the Index operator must be - * either a Buffer or a Package - */ - switch (operand[0]->reference.target_type) { - case ACPI_TYPE_BUFFER_FIELD: - - temp_desc = - operand[0]->reference.object; - - /* - * Create a new object that contains one element of the - * buffer -- the element pointed to by the index. - * - * NOTE: index into a buffer is NOT a pointer to a - * sub-buffer of the main buffer, it is only a pointer to a - * single element (byte) of the buffer! - */ - return_desc = - acpi_ut_create_internal_object - (ACPI_TYPE_INTEGER); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * Since we are returning the value of the buffer at the - * indexed location, we don't need to add an additional - * reference to the buffer itself. - */ - return_desc->integer.value = - temp_desc->buffer. - pointer[operand[0]->reference. - value]; - break; - - case ACPI_TYPE_PACKAGE: - - /* - * Return the referenced element of the package. We must - * add another reference to the referenced object, however. - */ - return_desc = - *(operand[0]->reference.where); - if (return_desc) { - acpi_ut_add_reference - (return_desc); - } - break; - - default: - - ACPI_ERROR((AE_INFO, - "Unknown Index TargetType %X in reference object %p", - operand[0]->reference. - target_type, operand[0])); - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - break; - - case ACPI_REFCLASS_REFOF: - - return_desc = operand[0]->reference.object; - - if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) == - ACPI_DESC_TYPE_NAMED) { - return_desc = - acpi_ns_get_attached_object((struct - acpi_namespace_node - *) - return_desc); - } - - /* Add another reference to the object! */ - - acpi_ut_add_reference(return_desc); - break; - - default: - ACPI_ERROR((AE_INFO, - "Unknown class in reference(%p) - %2.2X", - operand[0], - operand[0]->reference.class)); - - status = AE_TYPE; - goto cleanup; - } - } - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - cleanup: - - /* Delete return object on error */ - - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(return_desc); - } - - /* Save return object on success */ - - else { - walk_state->result_obj = return_desc; - } - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c deleted file mode 100644 index b01980df1365..000000000000 --- a/drivers/acpi/executer/exoparg2.c +++ /dev/null @@ -1,605 +0,0 @@ -/****************************************************************************** - * - * Module Name: exoparg2 - AML execution - opcodes with 2 arguments - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exoparg2") - -/*! - * Naming convention for AML interpreter execution routines. - * - * The routines that begin execution of AML opcodes are named with a common - * convention based upon the number of arguments, the number of target operands, - * and whether or not a value is returned: - * - * AcpiExOpcode_xA_yT_zR - * - * Where: - * - * xA - ARGUMENTS: The number of arguments (input operands) that are - * required for this opcode type (1 through 6 args). - * yT - TARGETS: The number of targets (output operands) that are required - * for this opcode type (0, 1, or 2 targets). - * zR - RETURN VALUE: Indicates whether this opcode type returns a value - * as the function return (0 or 1). - * - * The AcpiExOpcode* functions are called via the Dispatcher component with - * fully resolved operands. -!*/ -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_2A_0T_0R - * - * PARAMETERS: walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Execute opcode with two arguments, no target, and no return - * value. - * - * ALLOCATION: Deletes both operands - * - ******************************************************************************/ -acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - struct acpi_namespace_node *node; - u32 value; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - /* Examine the opcode */ - - switch (walk_state->opcode) { - case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */ - - /* The first operand is a namespace node */ - - node = (struct acpi_namespace_node *)operand[0]; - - /* Second value is the notify value */ - - value = (u32) operand[1]->integer.value; - - /* Are notifies allowed on this object? */ - - if (!acpi_ev_is_notify_object(node)) { - ACPI_ERROR((AE_INFO, - "Unexpected notify object type [%s]", - acpi_ut_get_type_name(node->type))); - - status = AE_AML_OPERAND_TYPE; - break; - } -#ifdef ACPI_GPE_NOTIFY_CHECK - /* - * GPE method wake/notify check. Here, we want to ensure that we - * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx - * GPE method during system runtime. If we do, the GPE is marked - * as "wake-only" and disabled. - * - * 1) Is the Notify() value == device_wake? - * 2) Is this a GPE deferred method? (An _Lxx or _Exx method) - * 3) Did the original GPE happen at system runtime? - * (versus during wake) - * - * If all three cases are true, this is a wake-only GPE that should - * be disabled at runtime. - */ - if (value == 2) { /* device_wake */ - status = - acpi_ev_check_for_wake_only_gpe(walk_state-> - gpe_event_info); - if (ACPI_FAILURE(status)) { - - /* AE_WAKE_ONLY_GPE only error, means ignore this notify */ - - return_ACPI_STATUS(AE_OK) - } - } -#endif - - /* - * Dispatch the notify to the appropriate handler - * NOTE: the request is queued for execution after this method - * completes. The notify handlers are NOT invoked synchronously - * from this thread -- because handlers may in turn run other - * control methods. - */ - status = acpi_ev_queue_notify_request(node, value); - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_2A_2T_1R - * - * PARAMETERS: walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets - * and one implicit return value. - * - ******************************************************************************/ - -acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *return_desc1 = NULL; - union acpi_operand_object *return_desc2 = NULL; - acpi_status status; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - /* Execute the opcode */ - - switch (walk_state->opcode) { - case AML_DIVIDE_OP: - - /* Divide (Dividend, Divisor, remainder_result quotient_result) */ - - return_desc1 = - acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc1) { - status = AE_NO_MEMORY; - goto cleanup; - } - - return_desc2 = - acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc2) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Quotient to return_desc1, remainder to return_desc2 */ - - status = acpi_ut_divide(operand[0]->integer.value, - operand[1]->integer.value, - &return_desc1->integer.value, - &return_desc2->integer.value); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - /* Store the results to the target reference operands */ - - status = acpi_ex_store(return_desc2, operand[2], walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - status = acpi_ex_store(return_desc1, operand[3], walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - cleanup: - /* - * Since the remainder is not returned indirectly, remove a reference to - * it. Only the quotient is returned indirectly. - */ - acpi_ut_remove_reference(return_desc2); - - if (ACPI_FAILURE(status)) { - - /* Delete the return object */ - - acpi_ut_remove_reference(return_desc1); - } - - /* Save return object (the remainder) on success */ - - else { - walk_state->result_obj = return_desc1; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_2A_1T_1R - * - * PARAMETERS: walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Execute opcode with two arguments, one target, and a return - * value. - * - ******************************************************************************/ - -acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *return_desc = NULL; - acpi_integer index; - acpi_status status = AE_OK; - acpi_size length; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - /* Execute the opcode */ - - if (walk_state->op_info->flags & AML_MATH) { - - /* All simple math opcodes (add, etc.) */ - - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - return_desc->integer.value = - acpi_ex_do_math_op(walk_state->opcode, - operand[0]->integer.value, - operand[1]->integer.value); - goto store_result_to_target; - } - - switch (walk_state->opcode) { - case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */ - - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* return_desc will contain the remainder */ - - status = acpi_ut_divide(operand[0]->integer.value, - operand[1]->integer.value, - NULL, &return_desc->integer.value); - break; - - case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */ - - status = acpi_ex_do_concatenate(operand[0], operand[1], - &return_desc, walk_state); - break; - - case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */ - - /* - * Input object is guaranteed to be a buffer at this point (it may have - * been converted.) Copy the raw buffer data to a new object of - * type String. - */ - - /* - * Get the length of the new string. It is the smallest of: - * 1) Length of the input buffer - * 2) Max length as specified in the to_string operator - * 3) Length of input buffer up to a zero byte (null terminator) - * - * NOTE: A length of zero is ok, and will create a zero-length, null - * terminated string. - */ - length = 0; - while ((length < operand[0]->buffer.length) && - (length < operand[1]->integer.value) && - (operand[0]->buffer.pointer[length])) { - length++; - } - - /* Allocate a new string object */ - - return_desc = acpi_ut_create_string_object(length); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * Copy the raw buffer data with no transform. - * (NULL terminated already) - */ - ACPI_MEMCPY(return_desc->string.pointer, - operand[0]->buffer.pointer, length); - break; - - case AML_CONCAT_RES_OP: - - /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */ - - status = acpi_ex_concat_template(operand[0], operand[1], - &return_desc, walk_state); - break; - - case AML_INDEX_OP: /* Index (Source Index Result) */ - - /* Create the internal return object */ - - return_desc = - acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Initialize the Index reference object */ - - index = operand[1]->integer.value; - return_desc->reference.value = (u32) index; - return_desc->reference.class = ACPI_REFCLASS_INDEX; - - /* - * At this point, the Source operand is a String, Buffer, or Package. - * Verify that the index is within range. - */ - switch (ACPI_GET_OBJECT_TYPE(operand[0])) { - case ACPI_TYPE_STRING: - - if (index >= operand[0]->string.length) { - status = AE_AML_STRING_LIMIT; - } - - return_desc->reference.target_type = - ACPI_TYPE_BUFFER_FIELD; - break; - - case ACPI_TYPE_BUFFER: - - if (index >= operand[0]->buffer.length) { - status = AE_AML_BUFFER_LIMIT; - } - - return_desc->reference.target_type = - ACPI_TYPE_BUFFER_FIELD; - break; - - case ACPI_TYPE_PACKAGE: - - if (index >= operand[0]->package.count) { - status = AE_AML_PACKAGE_LIMIT; - } - - return_desc->reference.target_type = ACPI_TYPE_PACKAGE; - return_desc->reference.where = - &operand[0]->package.elements[index]; - break; - - default: - - status = AE_AML_INTERNAL; - goto cleanup; - } - - /* Failure means that the Index was beyond the end of the object */ - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Index (%X%8.8X) is beyond end of object", - ACPI_FORMAT_UINT64(index))); - goto cleanup; - } - - /* - * Save the target object and add a reference to it for the life - * of the index - */ - return_desc->reference.object = operand[0]; - acpi_ut_add_reference(operand[0]); - - /* Store the reference to the Target */ - - status = acpi_ex_store(return_desc, operand[2], walk_state); - - /* Return the reference */ - - walk_state->result_obj = return_desc; - goto cleanup; - - default: - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - break; - } - - store_result_to_target: - - if (ACPI_SUCCESS(status)) { - /* - * Store the result of the operation (which is now in return_desc) into - * the Target descriptor. - */ - status = acpi_ex_store(return_desc, operand[2], walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - if (!walk_state->result_obj) { - walk_state->result_obj = return_desc; - } - } - - cleanup: - - /* Delete return object on error */ - - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(return_desc); - walk_state->result_obj = NULL; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_2A_0T_1R - * - * PARAMETERS: walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value - * - ******************************************************************************/ - -acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *return_desc = NULL; - acpi_status status = AE_OK; - u8 logical_result = FALSE; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - /* Create the internal return object */ - - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Execute the Opcode */ - - if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) { - - /* logical_op (Operand0, Operand1) */ - - status = acpi_ex_do_logical_numeric_op(walk_state->opcode, - operand[0]->integer. - value, - operand[1]->integer. - value, &logical_result); - goto store_logical_result; - } else if (walk_state->op_info->flags & AML_LOGICAL) { - - /* logical_op (Operand0, Operand1) */ - - status = acpi_ex_do_logical_op(walk_state->opcode, operand[0], - operand[1], &logical_result); - goto store_logical_result; - } - - switch (walk_state->opcode) { - case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */ - - status = - acpi_ex_acquire_mutex(operand[1], operand[0], walk_state); - if (status == AE_TIME) { - logical_result = TRUE; /* TRUE = Acquire timed out */ - status = AE_OK; - } - break; - - case AML_WAIT_OP: /* Wait (event_object, Timeout) */ - - status = acpi_ex_system_wait_event(operand[1], operand[0]); - if (status == AE_TIME) { - logical_result = TRUE; /* TRUE, Wait timed out */ - status = AE_OK; - } - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - store_logical_result: - /* - * Set return value to according to logical_result. logical TRUE (all ones) - * Default is FALSE (zero) - */ - if (logical_result) { - return_desc->integer.value = ACPI_INTEGER_MAX; - } - - cleanup: - - /* Delete return object on error */ - - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(return_desc); - } - - /* Save return object on success */ - - else { - walk_state->result_obj = return_desc; - } - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c deleted file mode 100644 index 26dbd5c2c1da..000000000000 --- a/drivers/acpi/executer/exoparg3.c +++ /dev/null @@ -1,273 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exoparg3 - AML execution - opcodes with 3 arguments - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exoparg3") - -/*! - * Naming convention for AML interpreter execution routines. - * - * The routines that begin execution of AML opcodes are named with a common - * convention based upon the number of arguments, the number of target operands, - * and whether or not a value is returned: - * - * AcpiExOpcode_xA_yT_zR - * - * Where: - * - * xA - ARGUMENTS: The number of arguments (input operands) that are - * required for this opcode type (1 through 6 args). - * yT - TARGETS: The number of targets (output operands) that are required - * for this opcode type (0, 1, or 2 targets). - * zR - RETURN VALUE: Indicates whether this opcode type returns a value - * as the function return (0 or 1). - * - * The AcpiExOpcode* functions are called via the Dispatcher component with - * fully resolved operands. -!*/ -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_3A_0T_0R - * - * PARAMETERS: walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Execute Triadic operator (3 operands) - * - ******************************************************************************/ -acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - struct acpi_signal_fatal_info *fatal; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - switch (walk_state->opcode) { - case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */ - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", - (u32) operand[0]->integer.value, - (u32) operand[1]->integer.value, - (u32) operand[2]->integer.value)); - - fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); - if (fatal) { - fatal->type = (u32) operand[0]->integer.value; - fatal->code = (u32) operand[1]->integer.value; - fatal->argument = (u32) operand[2]->integer.value; - } - - /* Always signal the OS! */ - - status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal); - - /* Might return while OS is shutting down, just continue */ - - ACPI_FREE(fatal); - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - cleanup: - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_3A_1T_1R - * - * PARAMETERS: walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Execute Triadic operator (3 operands) - * - ******************************************************************************/ - -acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *return_desc = NULL; - char *buffer = NULL; - acpi_status status = AE_OK; - acpi_integer index; - acpi_size length; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - switch (walk_state->opcode) { - case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */ - - /* - * Create the return object. The Source operand is guaranteed to be - * either a String or a Buffer, so just use its type. - */ - return_desc = - acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE - (operand[0])); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Get the Integer values from the objects */ - - index = operand[1]->integer.value; - length = (acpi_size) operand[2]->integer.value; - - /* - * If the index is beyond the length of the String/Buffer, or if the - * requested length is zero, return a zero-length String/Buffer - */ - if (index >= operand[0]->string.length) { - length = 0; - } - - /* Truncate request if larger than the actual String/Buffer */ - - else if ((index + length) > operand[0]->string.length) { - length = (acpi_size) operand[0]->string.length - - (acpi_size) index; - } - - /* Strings always have a sub-pointer, not so for buffers */ - - switch (ACPI_GET_OBJECT_TYPE(operand[0])) { - case ACPI_TYPE_STRING: - - /* Always allocate a new buffer for the String */ - - buffer = ACPI_ALLOCATE_ZEROED((acpi_size) length + 1); - if (!buffer) { - status = AE_NO_MEMORY; - goto cleanup; - } - break; - - case ACPI_TYPE_BUFFER: - - /* If the requested length is zero, don't allocate a buffer */ - - if (length > 0) { - - /* Allocate a new buffer for the Buffer */ - - buffer = ACPI_ALLOCATE_ZEROED(length); - if (!buffer) { - status = AE_NO_MEMORY; - goto cleanup; - } - } - break; - - default: /* Should not happen */ - - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - - if (buffer) { - - /* We have a buffer, copy the portion requested */ - - ACPI_MEMCPY(buffer, operand[0]->string.pointer + index, - length); - } - - /* Set the length of the new String/Buffer */ - - return_desc->string.pointer = buffer; - return_desc->string.length = (u32) length; - - /* Mark buffer initialized */ - - return_desc->buffer.flags |= AOPOBJ_DATA_VALID; - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - /* Store the result in the target */ - - status = acpi_ex_store(return_desc, operand[3], walk_state); - - cleanup: - - /* Delete return object on error */ - - if (ACPI_FAILURE(status) || walk_state->result_obj) { - acpi_ut_remove_reference(return_desc); - walk_state->result_obj = NULL; - } - - /* Set the return object and exit */ - - else { - walk_state->result_obj = return_desc; - } - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c deleted file mode 100644 index bbbba504979f..000000000000 --- a/drivers/acpi/executer/exoparg6.c +++ /dev/null @@ -1,341 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exoparg6 - AML execution - opcodes with 6 arguments - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exoparg6") - -/*! - * Naming convention for AML interpreter execution routines. - * - * The routines that begin execution of AML opcodes are named with a common - * convention based upon the number of arguments, the number of target operands, - * and whether or not a value is returned: - * - * AcpiExOpcode_xA_yT_zR - * - * Where: - * - * xA - ARGUMENTS: The number of arguments (input operands) that are - * required for this opcode type (1 through 6 args). - * yT - TARGETS: The number of targets (output operands) that are required - * for this opcode type (0, 1, or 2 targets). - * zR - RETURN VALUE: Indicates whether this opcode type returns a value - * as the function return (0 or 1). - * - * The AcpiExOpcode* functions are called via the Dispatcher component with - * fully resolved operands. -!*/ -/* Local prototypes */ -static u8 -acpi_ex_do_match(u32 match_op, - union acpi_operand_object *package_obj, - union acpi_operand_object *match_obj); - -/******************************************************************************* - * - * FUNCTION: acpi_ex_do_match - * - * PARAMETERS: match_op - The AML match operand - * package_obj - Object from the target package - * match_obj - Object to be matched - * - * RETURN: TRUE if the match is successful, FALSE otherwise - * - * DESCRIPTION: Implements the low-level match for the ASL Match operator. - * Package elements will be implicitly converted to the type of - * the match object (Integer/Buffer/String). - * - ******************************************************************************/ - -static u8 -acpi_ex_do_match(u32 match_op, - union acpi_operand_object *package_obj, - union acpi_operand_object *match_obj) -{ - u8 logical_result = TRUE; - acpi_status status; - - /* - * Note: Since the package_obj/match_obj ordering is opposite to that of - * the standard logical operators, we have to reverse them when we call - * do_logical_op in order to make the implicit conversion rules work - * correctly. However, this means we have to flip the entire equation - * also. A bit ugly perhaps, but overall, better than fussing the - * parameters around at runtime, over and over again. - * - * Below, P[i] refers to the package element, M refers to the Match object. - */ - switch (match_op) { - case MATCH_MTR: - - /* Always true */ - - break; - - case MATCH_MEQ: - - /* - * True if equal: (P[i] == M) - * Change to: (M == P[i]) - */ - status = - acpi_ex_do_logical_op(AML_LEQUAL_OP, match_obj, package_obj, - &logical_result); - if (ACPI_FAILURE(status)) { - return (FALSE); - } - break; - - case MATCH_MLE: - - /* - * True if less than or equal: (P[i] <= M) (P[i] not_greater than M) - * Change to: (M >= P[i]) (M not_less than P[i]) - */ - status = - acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj, - &logical_result); - if (ACPI_FAILURE(status)) { - return (FALSE); - } - logical_result = (u8) ! logical_result; - break; - - case MATCH_MLT: - - /* - * True if less than: (P[i] < M) - * Change to: (M > P[i]) - */ - status = - acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj, - package_obj, &logical_result); - if (ACPI_FAILURE(status)) { - return (FALSE); - } - break; - - case MATCH_MGE: - - /* - * True if greater than or equal: (P[i] >= M) (P[i] not_less than M) - * Change to: (M <= P[i]) (M not_greater than P[i]) - */ - status = - acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj, - package_obj, &logical_result); - if (ACPI_FAILURE(status)) { - return (FALSE); - } - logical_result = (u8) ! logical_result; - break; - - case MATCH_MGT: - - /* - * True if greater than: (P[i] > M) - * Change to: (M < P[i]) - */ - status = - acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj, - &logical_result); - if (ACPI_FAILURE(status)) { - return (FALSE); - } - break; - - default: - - /* Undefined */ - - return (FALSE); - } - - return logical_result; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_opcode_6A_0T_1R - * - * PARAMETERS: walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Execute opcode with 6 arguments, no target, and a return value - * - ******************************************************************************/ - -acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) -{ - union acpi_operand_object **operand = &walk_state->operands[0]; - union acpi_operand_object *return_desc = NULL; - acpi_status status = AE_OK; - acpi_integer index; - union acpi_operand_object *this_element; - - ACPI_FUNCTION_TRACE_STR(ex_opcode_6A_0T_1R, - acpi_ps_get_opcode_name(walk_state->opcode)); - - switch (walk_state->opcode) { - case AML_MATCH_OP: - /* - * Match (search_pkg[0], match_op1[1], match_obj1[2], - * match_op2[3], match_obj2[4], start_index[5]) - */ - - /* Validate both Match Term Operators (MTR, MEQ, etc.) */ - - if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) || - (operand[3]->integer.value > MAX_MATCH_OPERATOR)) { - ACPI_ERROR((AE_INFO, "Match operator out of range")); - status = AE_AML_OPERAND_VALUE; - goto cleanup; - } - - /* Get the package start_index, validate against the package length */ - - index = operand[5]->integer.value; - if (index >= operand[0]->package.count) { - ACPI_ERROR((AE_INFO, - "Index (%X%8.8X) beyond package end (%X)", - ACPI_FORMAT_UINT64(index), - operand[0]->package.count)); - status = AE_AML_PACKAGE_LIMIT; - goto cleanup; - } - - /* Create an integer for the return value */ - - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - status = AE_NO_MEMORY; - goto cleanup; - - } - - /* Default return value if no match found */ - - return_desc->integer.value = ACPI_INTEGER_MAX; - - /* - * Examine each element until a match is found. Both match conditions - * must be satisfied for a match to occur. Within the loop, - * "continue" signifies that the current element does not match - * and the next should be examined. - * - * Upon finding a match, the loop will terminate via "break" at - * the bottom. If it terminates "normally", match_value will be - * ACPI_INTEGER_MAX (Ones) (its initial value) indicating that no - * match was found. - */ - for (; index < operand[0]->package.count; index++) { - - /* Get the current package element */ - - this_element = operand[0]->package.elements[index]; - - /* Treat any uninitialized (NULL) elements as non-matching */ - - if (!this_element) { - continue; - } - - /* - * Both match conditions must be satisfied. Execution of a continue - * (proceed to next iteration of enclosing for loop) signifies a - * non-match. - */ - if (!acpi_ex_do_match((u32) operand[1]->integer.value, - this_element, operand[2])) { - continue; - } - - if (!acpi_ex_do_match((u32) operand[3]->integer.value, - this_element, operand[4])) { - continue; - } - - /* Match found: Index is the return value */ - - return_desc->integer.value = index; - break; - } - break; - - case AML_LOAD_TABLE_OP: - - status = acpi_ex_load_table_op(walk_state, &return_desc); - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", - walk_state->opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - cleanup: - - /* Delete return object on error */ - - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(return_desc); - } - - /* Save return object on success */ - - else { - walk_state->result_obj = return_desc; - } - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c deleted file mode 100644 index 8f2baa934e95..000000000000 --- a/drivers/acpi/executer/exprep.c +++ /dev/null @@ -1,590 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exprep") - -/* Local prototypes */ -static u32 -acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, - u8 field_flags, u32 * return_byte_alignment); - -#ifdef ACPI_UNDER_DEVELOPMENT - -static u32 -acpi_ex_generate_access(u32 field_bit_offset, - u32 field_bit_length, u32 region_length); - -/******************************************************************************* - * - * FUNCTION: acpi_ex_generate_access - * - * PARAMETERS: field_bit_offset - Start of field within parent region/buffer - * field_bit_length - Length of field in bits - * region_length - Length of parent in bytes - * - * RETURN: Field granularity (8, 16, 32 or 64) and - * byte_alignment (1, 2, 3, or 4) - * - * DESCRIPTION: Generate an optimal access width for fields defined with the - * any_acc keyword. - * - * NOTE: Need to have the region_length in order to check for boundary - * conditions (end-of-region). However, the region_length is a deferred - * operation. Therefore, to complete this implementation, the generation - * of this access width must be deferred until the region length has - * been evaluated. - * - ******************************************************************************/ - -static u32 -acpi_ex_generate_access(u32 field_bit_offset, - u32 field_bit_length, u32 region_length) -{ - u32 field_byte_length; - u32 field_byte_offset; - u32 field_byte_end_offset; - u32 access_byte_width; - u32 field_start_offset; - u32 field_end_offset; - u32 minimum_access_width = 0xFFFFFFFF; - u32 minimum_accesses = 0xFFFFFFFF; - u32 accesses; - - ACPI_FUNCTION_TRACE(ex_generate_access); - - /* Round Field start offset and length to "minimal" byte boundaries */ - - field_byte_offset = ACPI_DIV_8(ACPI_ROUND_DOWN(field_bit_offset, 8)); - field_byte_end_offset = ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length + - field_bit_offset, 8)); - field_byte_length = field_byte_end_offset - field_byte_offset; - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Bit length %d, Bit offset %d\n", - field_bit_length, field_bit_offset)); - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Byte Length %d, Byte Offset %d, End Offset %d\n", - field_byte_length, field_byte_offset, - field_byte_end_offset)); - - /* - * Iterative search for the maximum access width that is both aligned - * and does not go beyond the end of the region - * - * Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes) - */ - for (access_byte_width = 1; access_byte_width <= 8; - access_byte_width <<= 1) { - /* - * 1) Round end offset up to next access boundary and make sure that - * this does not go beyond the end of the parent region. - * 2) When the Access width is greater than the field_byte_length, we - * are done. (This does not optimize for the perfectly aligned - * case yet). - */ - if (ACPI_ROUND_UP(field_byte_end_offset, access_byte_width) <= - region_length) { - field_start_offset = - ACPI_ROUND_DOWN(field_byte_offset, - access_byte_width) / - access_byte_width; - - field_end_offset = - ACPI_ROUND_UP((field_byte_length + - field_byte_offset), - access_byte_width) / - access_byte_width; - - accesses = field_end_offset - field_start_offset; - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "AccessWidth %d end is within region\n", - access_byte_width)); - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Field Start %d, Field End %d -- requires %d accesses\n", - field_start_offset, field_end_offset, - accesses)); - - /* Single access is optimal */ - - if (accesses <= 1) { - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Entire field can be accessed with one operation of size %d\n", - access_byte_width)); - return_VALUE(access_byte_width); - } - - /* - * Fits in the region, but requires more than one read/write. - * try the next wider access on next iteration - */ - if (accesses < minimum_accesses) { - minimum_accesses = accesses; - minimum_access_width = access_byte_width; - } - } else { - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "AccessWidth %d end is NOT within region\n", - access_byte_width)); - if (access_byte_width == 1) { - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Field goes beyond end-of-region!\n")); - - /* Field does not fit in the region at all */ - - return_VALUE(0); - } - - /* - * This width goes beyond the end-of-region, back off to - * previous access - */ - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Backing off to previous optimal access width of %d\n", - minimum_access_width)); - return_VALUE(minimum_access_width); - } - } - - /* - * Could not read/write field with one operation, - * just use max access width - */ - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Cannot access field in one operation, using width 8\n")); - return_VALUE(8); -} -#endif /* ACPI_UNDER_DEVELOPMENT */ - -/******************************************************************************* - * - * FUNCTION: acpi_ex_decode_field_access - * - * PARAMETERS: obj_desc - Field object - * field_flags - Encoded fieldflags (contains access bits) - * return_byte_alignment - Where the byte alignment is returned - * - * RETURN: Field granularity (8, 16, 32 or 64) and - * byte_alignment (1, 2, 3, or 4) - * - * DESCRIPTION: Decode the access_type bits of a field definition. - * - ******************************************************************************/ - -static u32 -acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, - u8 field_flags, u32 * return_byte_alignment) -{ - u32 access; - u32 byte_alignment; - u32 bit_length; - - ACPI_FUNCTION_TRACE(ex_decode_field_access); - - access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK); - - switch (access) { - case AML_FIELD_ACCESS_ANY: - -#ifdef ACPI_UNDER_DEVELOPMENT - byte_alignment = - acpi_ex_generate_access(obj_desc->common_field. - start_field_bit_offset, - obj_desc->common_field.bit_length, - 0xFFFFFFFF - /* Temp until we pass region_length as parameter */ - ); - bit_length = byte_alignment * 8; -#endif - - byte_alignment = 1; - bit_length = 8; - break; - - case AML_FIELD_ACCESS_BYTE: - case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */ - byte_alignment = 1; - bit_length = 8; - break; - - case AML_FIELD_ACCESS_WORD: - byte_alignment = 2; - bit_length = 16; - break; - - case AML_FIELD_ACCESS_DWORD: - byte_alignment = 4; - bit_length = 32; - break; - - case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ - byte_alignment = 8; - bit_length = 64; - break; - - default: - /* Invalid field access type */ - - ACPI_ERROR((AE_INFO, "Unknown field access type %X", access)); - return_UINT32(0); - } - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { - /* - * buffer_field access can be on any byte boundary, so the - * byte_alignment is always 1 byte -- regardless of any byte_alignment - * implied by the field access type. - */ - byte_alignment = 1; - } - - *return_byte_alignment = byte_alignment; - return_UINT32(bit_length); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_prep_common_field_object - * - * PARAMETERS: obj_desc - The field object - * field_flags - Access, lock_rule, and update_rule. - * The format of a field_flag is described - * in the ACPI specification - * field_attribute - Special attributes (not used) - * field_bit_position - Field start position - * field_bit_length - Field length in number of bits - * - * RETURN: Status - * - * DESCRIPTION: Initialize the areas of the field object that are common - * to the various types of fields. Note: This is very "sensitive" - * code because we are solving the general case for field - * alignment. - * - ******************************************************************************/ - -acpi_status -acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, - u8 field_flags, - u8 field_attribute, - u32 field_bit_position, u32 field_bit_length) -{ - u32 access_bit_width; - u32 byte_alignment; - u32 nearest_byte_address; - - ACPI_FUNCTION_TRACE(ex_prep_common_field_object); - - /* - * Note: the structure being initialized is the - * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common - * area are initialized by this procedure. - */ - obj_desc->common_field.field_flags = field_flags; - obj_desc->common_field.attribute = field_attribute; - obj_desc->common_field.bit_length = field_bit_length; - - /* - * Decode the access type so we can compute offsets. The access type gives - * two pieces of information - the width of each field access and the - * necessary byte_alignment (address granularity) of the access. - * - * For any_acc, the access_bit_width is the largest width that is both - * necessary and possible in an attempt to access the whole field in one - * I/O operation. However, for any_acc, the byte_alignment is always one - * byte. - * - * For all Buffer Fields, the byte_alignment is always one byte. - * - * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is - * the same (equivalent) as the byte_alignment. - */ - access_bit_width = acpi_ex_decode_field_access(obj_desc, field_flags, - &byte_alignment); - if (!access_bit_width) { - return_ACPI_STATUS(AE_AML_OPERAND_VALUE); - } - - /* Setup width (access granularity) fields */ - - obj_desc->common_field.access_byte_width = (u8) - ACPI_DIV_8(access_bit_width); /* 1, 2, 4, 8 */ - - obj_desc->common_field.access_bit_width = (u8) access_bit_width; - - /* - * base_byte_offset is the address of the start of the field within the - * region. It is the byte address of the first *datum* (field-width data - * unit) of the field. (i.e., the first datum that contains at least the - * first *bit* of the field.) - * - * Note: byte_alignment is always either equal to the access_bit_width or 8 - * (Byte access), and it defines the addressing granularity of the parent - * region or buffer. - */ - nearest_byte_address = - ACPI_ROUND_BITS_DOWN_TO_BYTES(field_bit_position); - obj_desc->common_field.base_byte_offset = (u32) - ACPI_ROUND_DOWN(nearest_byte_address, byte_alignment); - - /* - * start_field_bit_offset is the offset of the first bit of the field within - * a field datum. - */ - obj_desc->common_field.start_field_bit_offset = (u8) - (field_bit_position - - ACPI_MUL_8(obj_desc->common_field.base_byte_offset)); - - /* - * Does the entire field fit within a single field access element? (datum) - * (i.e., without crossing a datum boundary) - */ - if ((obj_desc->common_field.start_field_bit_offset + - field_bit_length) <= (u16) access_bit_width) { - obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_prep_field_value - * - * PARAMETERS: Info - Contains all field creation info - * - * RETURN: Status - * - * DESCRIPTION: Construct an union acpi_operand_object of type def_field and - * connect it to the parent Node. - * - ******************************************************************************/ - -acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) -{ - union acpi_operand_object *obj_desc; - union acpi_operand_object *second_desc = NULL; - u32 type; - acpi_status status; - - ACPI_FUNCTION_TRACE(ex_prep_field_value); - - /* Parameter validation */ - - if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) { - if (!info->region_node) { - ACPI_ERROR((AE_INFO, "Null RegionNode")); - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - type = acpi_ns_get_type(info->region_node); - if (type != ACPI_TYPE_REGION) { - ACPI_ERROR((AE_INFO, - "Needed Region, found type %X (%s)", - type, acpi_ut_get_type_name(type))); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - } - - /* Allocate a new field object */ - - obj_desc = acpi_ut_create_internal_object(info->field_type); - if (!obj_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Initialize areas of the object that are common to all fields */ - - obj_desc->common_field.node = info->field_node; - status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags, - info->attribute, - info->field_bit_position, - info->field_bit_length); - if (ACPI_FAILURE(status)) { - acpi_ut_delete_object_desc(obj_desc); - return_ACPI_STATUS(status); - } - - /* Initialize areas of the object that are specific to the field type */ - - switch (info->field_type) { - case ACPI_TYPE_LOCAL_REGION_FIELD: - - obj_desc->field.region_obj = - acpi_ns_get_attached_object(info->region_node); - - /* An additional reference for the container */ - - acpi_ut_add_reference(obj_desc->field.region_obj); - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", - obj_desc->field.start_field_bit_offset, - obj_desc->field.base_byte_offset, - obj_desc->field.access_byte_width, - obj_desc->field.region_obj)); - break; - - case ACPI_TYPE_LOCAL_BANK_FIELD: - - obj_desc->bank_field.value = info->bank_value; - obj_desc->bank_field.region_obj = - acpi_ns_get_attached_object(info->region_node); - obj_desc->bank_field.bank_obj = - acpi_ns_get_attached_object(info->register_node); - - /* An additional reference for the attached objects */ - - acpi_ut_add_reference(obj_desc->bank_field.region_obj); - acpi_ut_add_reference(obj_desc->bank_field.bank_obj); - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n", - obj_desc->bank_field.start_field_bit_offset, - obj_desc->bank_field.base_byte_offset, - obj_desc->field.access_byte_width, - obj_desc->bank_field.region_obj, - obj_desc->bank_field.bank_obj)); - - /* - * Remember location in AML stream of the field unit - * opcode and operands -- since the bank_value - * operands must be evaluated. - */ - second_desc = obj_desc->common.next_object; - second_desc->extra.aml_start = - ACPI_CAST_PTR(union acpi_parse_object, - info->data_register_node)->named.data; - second_desc->extra.aml_length = - ACPI_CAST_PTR(union acpi_parse_object, - info->data_register_node)->named.length; - - break; - - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - /* Get the Index and Data registers */ - - obj_desc->index_field.index_obj = - acpi_ns_get_attached_object(info->register_node); - obj_desc->index_field.data_obj = - acpi_ns_get_attached_object(info->data_register_node); - - if (!obj_desc->index_field.data_obj - || !obj_desc->index_field.index_obj) { - ACPI_ERROR((AE_INFO, - "Null Index Object during field prep")); - acpi_ut_delete_object_desc(obj_desc); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - /* An additional reference for the attached objects */ - - acpi_ut_add_reference(obj_desc->index_field.data_obj); - acpi_ut_add_reference(obj_desc->index_field.index_obj); - - /* - * April 2006: Changed to match MS behavior - * - * The value written to the Index register is the byte offset of the - * target field in units of the granularity of the index_field - * - * Previously, the value was calculated as an index in terms of the - * width of the Data register, as below: - * - * obj_desc->index_field.Value = (u32) - * (Info->field_bit_position / ACPI_MUL_8 ( - * obj_desc->Field.access_byte_width)); - * - * February 2006: Tried value as a byte offset: - * obj_desc->index_field.Value = (u32) - * ACPI_DIV_8 (Info->field_bit_position); - */ - obj_desc->index_field.value = - (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position), - obj_desc->index_field. - access_byte_width); - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", - obj_desc->index_field.start_field_bit_offset, - obj_desc->index_field.base_byte_offset, - obj_desc->index_field.value, - obj_desc->field.access_byte_width, - obj_desc->index_field.index_obj, - obj_desc->index_field.data_obj)); - break; - - default: - /* No other types should get here */ - break; - } - - /* - * Store the constructed descriptor (obj_desc) into the parent Node, - * preserving the current type of that named_obj. - */ - status = acpi_ns_attach_object(info->field_node, obj_desc, - acpi_ns_get_type(info->field_node)); - - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Set NamedObj %p [%4.4s], ObjDesc %p\n", - info->field_node, - acpi_ut_get_node_name(info->field_node), obj_desc)); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c deleted file mode 100644 index ceb269e45aba..000000000000 --- a/drivers/acpi/executer/exregion.c +++ /dev/null @@ -1,499 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exregion - ACPI default op_region (address space) handlers - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exregion") - -/******************************************************************************* - * - * FUNCTION: acpi_ex_system_memory_space_handler - * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write - * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value - * handler_context - Pointer to Handler's context - * region_context - Pointer to context specific to the - * accessed region - * - * RETURN: Status - * - * DESCRIPTION: Handler for the System Memory address space (Op Region) - * - ******************************************************************************/ -acpi_status -acpi_ex_system_memory_space_handler(u32 function, - acpi_physical_address address, - u32 bit_width, - acpi_integer * value, - void *handler_context, void *region_context) -{ - acpi_status status = AE_OK; - void *logical_addr_ptr = NULL; - struct acpi_mem_space_context *mem_info = region_context; - u32 length; - acpi_size window_size; -#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED - u32 remainder; -#endif - - ACPI_FUNCTION_TRACE(ex_system_memory_space_handler); - - /* Validate and translate the bit width */ - - switch (bit_width) { - case 8: - length = 1; - break; - - case 16: - length = 2; - break; - - case 32: - length = 4; - break; - - case 64: - length = 8; - break; - - default: - ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %d", - bit_width)); - return_ACPI_STATUS(AE_AML_OPERAND_VALUE); - } - -#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED - /* - * Hardware does not support non-aligned data transfers, we must verify - * the request. - */ - (void)acpi_ut_short_divide((acpi_integer) address, length, NULL, - &remainder); - if (remainder != 0) { - return_ACPI_STATUS(AE_AML_ALIGNMENT); - } -#endif - - /* - * Does the request fit into the cached memory mapping? - * Is 1) Address below the current mapping? OR - * 2) Address beyond the current mapping? - */ - if ((address < mem_info->mapped_physical_address) || - (((acpi_integer) address + length) > ((acpi_integer) - mem_info-> - mapped_physical_address + - mem_info->mapped_length))) { - /* - * The request cannot be resolved by the current memory mapping; - * Delete the existing mapping and create a new one. - */ - if (mem_info->mapped_length) { - - /* Valid mapping, delete it */ - - acpi_os_unmap_memory(mem_info->mapped_logical_address, - mem_info->mapped_length); - } - - /* - * Don't attempt to map memory beyond the end of the region, and - * constrain the maximum mapping size to something reasonable. - */ - window_size = (acpi_size) - ((mem_info->address + mem_info->length) - address); - - if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) { - window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE; - } - - /* Create a new mapping starting at the address given */ - - mem_info->mapped_logical_address = - acpi_os_map_memory((acpi_physical_address) address, window_size); - if (!mem_info->mapped_logical_address) { - ACPI_ERROR((AE_INFO, - "Could not map memory at %8.8X%8.8X, size %X", - ACPI_FORMAT_NATIVE_UINT(address), - (u32) window_size)); - mem_info->mapped_length = 0; - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Save the physical address and mapping size */ - - mem_info->mapped_physical_address = address; - mem_info->mapped_length = window_size; - } - - /* - * Generate a logical pointer corresponding to the address we want to - * access - */ - logical_addr_ptr = mem_info->mapped_logical_address + - ((acpi_integer) address - - (acpi_integer) mem_info->mapped_physical_address); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", - bit_width, function, - ACPI_FORMAT_NATIVE_UINT(address))); - - /* - * Perform the memory read or write - * - * Note: For machines that do not support non-aligned transfers, the target - * address was checked for alignment above. We do not attempt to break the - * transfer up into smaller (byte-size) chunks because the AML specifically - * asked for a transfer width that the hardware may require. - */ - switch (function) { - case ACPI_READ: - - *value = 0; - switch (bit_width) { - case 8: - *value = (acpi_integer) ACPI_GET8(logical_addr_ptr); - break; - - case 16: - *value = (acpi_integer) ACPI_GET16(logical_addr_ptr); - break; - - case 32: - *value = (acpi_integer) ACPI_GET32(logical_addr_ptr); - break; - - case 64: - *value = (acpi_integer) ACPI_GET64(logical_addr_ptr); - break; - - default: - /* bit_width was already validated */ - break; - } - break; - - case ACPI_WRITE: - - switch (bit_width) { - case 8: - ACPI_SET8(logical_addr_ptr) = (u8) * value; - break; - - case 16: - ACPI_SET16(logical_addr_ptr) = (u16) * value; - break; - - case 32: - ACPI_SET32(logical_addr_ptr) = (u32) * value; - break; - - case 64: - ACPI_SET64(logical_addr_ptr) = (u64) * value; - break; - - default: - /* bit_width was already validated */ - break; - } - break; - - default: - status = AE_BAD_PARAMETER; - break; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_system_io_space_handler - * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write - * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value - * handler_context - Pointer to Handler's context - * region_context - Pointer to context specific to the - * accessed region - * - * RETURN: Status - * - * DESCRIPTION: Handler for the System IO address space (Op Region) - * - ******************************************************************************/ - -acpi_status -acpi_ex_system_io_space_handler(u32 function, - acpi_physical_address address, - u32 bit_width, - acpi_integer * value, - void *handler_context, void *region_context) -{ - acpi_status status = AE_OK; - u32 value32; - - ACPI_FUNCTION_TRACE(ex_system_io_space_handler); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", - bit_width, function, - ACPI_FORMAT_NATIVE_UINT(address))); - - /* Decode the function parameter */ - - switch (function) { - case ACPI_READ: - - status = acpi_os_read_port((acpi_io_address) address, - &value32, bit_width); - *value = value32; - break; - - case ACPI_WRITE: - - status = acpi_os_write_port((acpi_io_address) address, - (u32) * value, bit_width); - break; - - default: - status = AE_BAD_PARAMETER; - break; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_pci_config_space_handler - * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write - * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value - * handler_context - Pointer to Handler's context - * region_context - Pointer to context specific to the - * accessed region - * - * RETURN: Status - * - * DESCRIPTION: Handler for the PCI Config address space (Op Region) - * - ******************************************************************************/ - -acpi_status -acpi_ex_pci_config_space_handler(u32 function, - acpi_physical_address address, - u32 bit_width, - acpi_integer * value, - void *handler_context, void *region_context) -{ - acpi_status status = AE_OK; - struct acpi_pci_id *pci_id; - u16 pci_register; - u32 value32; - - ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); - - /* - * The arguments to acpi_os(Read|Write)pci_configuration are: - * - * pci_segment is the PCI bus segment range 0-31 - * pci_bus is the PCI bus number range 0-255 - * pci_device is the PCI device number range 0-31 - * pci_function is the PCI device function number - * pci_register is the Config space register range 0-255 bytes - * - * Value - input value for write, output address for read - * - */ - pci_id = (struct acpi_pci_id *)region_context; - pci_register = (u16) (u32) address; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Pci-Config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", - function, bit_width, pci_id->segment, pci_id->bus, - pci_id->device, pci_id->function, pci_register)); - - switch (function) { - case ACPI_READ: - - status = acpi_os_read_pci_configuration(pci_id, pci_register, - &value32, bit_width); - *value = value32; - break; - - case ACPI_WRITE: - - status = acpi_os_write_pci_configuration(pci_id, pci_register, - *value, bit_width); - break; - - default: - - status = AE_BAD_PARAMETER; - break; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_cmos_space_handler - * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write - * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value - * handler_context - Pointer to Handler's context - * region_context - Pointer to context specific to the - * accessed region - * - * RETURN: Status - * - * DESCRIPTION: Handler for the CMOS address space (Op Region) - * - ******************************************************************************/ - -acpi_status -acpi_ex_cmos_space_handler(u32 function, - acpi_physical_address address, - u32 bit_width, - acpi_integer * value, - void *handler_context, void *region_context) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ex_cmos_space_handler); - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_pci_bar_space_handler - * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write - * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value - * handler_context - Pointer to Handler's context - * region_context - Pointer to context specific to the - * accessed region - * - * RETURN: Status - * - * DESCRIPTION: Handler for the PCI bar_target address space (Op Region) - * - ******************************************************************************/ - -acpi_status -acpi_ex_pci_bar_space_handler(u32 function, - acpi_physical_address address, - u32 bit_width, - acpi_integer * value, - void *handler_context, void *region_context) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler); - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_data_table_space_handler - * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write - * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value - * handler_context - Pointer to Handler's context - * region_context - Pointer to context specific to the - * accessed region - * - * RETURN: Status - * - * DESCRIPTION: Handler for the Data Table address space (Op Region) - * - ******************************************************************************/ - -acpi_status -acpi_ex_data_table_space_handler(u32 function, - acpi_physical_address address, - u32 bit_width, - acpi_integer * value, - void *handler_context, void *region_context) -{ - ACPI_FUNCTION_TRACE(ex_data_table_space_handler); - - /* Perform the memory read or write */ - - switch (function) { - case ACPI_READ: - - ACPI_MEMCPY(ACPI_CAST_PTR(char, value), - ACPI_PHYSADDR_TO_PTR(address), - ACPI_DIV_8(bit_width)); - break; - - case ACPI_WRITE: - default: - - return_ACPI_STATUS(AE_SUPPORT); - } - - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c deleted file mode 100644 index 77df6e490e70..000000000000 --- a/drivers/acpi/executer/exresnte.c +++ /dev/null @@ -1,278 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exresnte - AML Interpreter object resolution - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exresnte") - -/******************************************************************************* - * - * FUNCTION: acpi_ex_resolve_node_to_value - * - * PARAMETERS: object_ptr - Pointer to a location that contains - * a pointer to a NS node, and will receive a - * pointer to the resolved object. - * walk_state - Current state. Valid only if executing AML - * code. NULL if simply resolving an object - * - * RETURN: Status - * - * DESCRIPTION: Resolve a Namespace node to a valued object - * - * Note: for some of the data types, the pointer attached to the Node - * can be either a pointer to an actual internal object or a pointer into the - * AML stream itself. These types are currently: - * - * ACPI_TYPE_INTEGER - * ACPI_TYPE_STRING - * ACPI_TYPE_BUFFER - * ACPI_TYPE_MUTEX - * ACPI_TYPE_PACKAGE - * - ******************************************************************************/ -acpi_status -acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, - struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - union acpi_operand_object *source_desc; - union acpi_operand_object *obj_desc = NULL; - struct acpi_namespace_node *node; - acpi_object_type entry_type; - - ACPI_FUNCTION_TRACE(ex_resolve_node_to_value); - - /* - * The stack pointer points to a struct acpi_namespace_node (Node). Get the - * object that is attached to the Node. - */ - node = *object_ptr; - source_desc = acpi_ns_get_attached_object(node); - entry_type = acpi_ns_get_type((acpi_handle) node); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n", - node, source_desc, - acpi_ut_get_type_name(entry_type))); - - if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) || - (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { - - /* There is always exactly one level of indirection */ - - node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object); - source_desc = acpi_ns_get_attached_object(node); - entry_type = acpi_ns_get_type((acpi_handle) node); - *object_ptr = node; - } - - /* - * Several object types require no further processing: - * 1) Device/Thermal objects don't have a "real" subobject, return the Node - * 2) Method locals and arguments have a pseudo-Node - * 3) 10/2007: Added method type to assist with Package construction. - */ - if ((entry_type == ACPI_TYPE_DEVICE) || - (entry_type == ACPI_TYPE_THERMAL) || - (entry_type == ACPI_TYPE_METHOD) || - (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { - return_ACPI_STATUS(AE_OK); - } - - if (!source_desc) { - ACPI_ERROR((AE_INFO, "No object attached to node %p", node)); - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - /* - * Action is based on the type of the Node, which indicates the type - * of the attached object or pointer - */ - switch (entry_type) { - case ACPI_TYPE_PACKAGE: - - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_PACKAGE) { - ACPI_ERROR((AE_INFO, "Object not a Package, type %s", - acpi_ut_get_object_type_name(source_desc))); - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - status = acpi_ds_get_package_arguments(source_desc); - if (ACPI_SUCCESS(status)) { - - /* Return an additional reference to the object */ - - obj_desc = source_desc; - acpi_ut_add_reference(obj_desc); - } - break; - - case ACPI_TYPE_BUFFER: - - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) { - ACPI_ERROR((AE_INFO, "Object not a Buffer, type %s", - acpi_ut_get_object_type_name(source_desc))); - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - status = acpi_ds_get_buffer_arguments(source_desc); - if (ACPI_SUCCESS(status)) { - - /* Return an additional reference to the object */ - - obj_desc = source_desc; - acpi_ut_add_reference(obj_desc); - } - break; - - case ACPI_TYPE_STRING: - - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) { - ACPI_ERROR((AE_INFO, "Object not a String, type %s", - acpi_ut_get_object_type_name(source_desc))); - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* Return an additional reference to the object */ - - obj_desc = source_desc; - acpi_ut_add_reference(obj_desc); - break; - - case ACPI_TYPE_INTEGER: - - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, "Object not a Integer, type %s", - acpi_ut_get_object_type_name(source_desc))); - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* Return an additional reference to the object */ - - obj_desc = source_desc; - acpi_ut_add_reference(obj_desc); - break; - - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "FieldRead Node=%p SourceDesc=%p Type=%X\n", - node, source_desc, entry_type)); - - status = - acpi_ex_read_data_from_field(walk_state, source_desc, - &obj_desc); - break; - - /* For these objects, just return the object attached to the Node */ - - case ACPI_TYPE_MUTEX: - case ACPI_TYPE_POWER: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_EVENT: - case ACPI_TYPE_REGION: - - /* Return an additional reference to the object */ - - obj_desc = source_desc; - acpi_ut_add_reference(obj_desc); - break; - - /* TYPE_ANY is untyped, and thus there is no object associated with it */ - - case ACPI_TYPE_ANY: - - ACPI_ERROR((AE_INFO, - "Untyped entry %p, no attached object!", node)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */ - - case ACPI_TYPE_LOCAL_REFERENCE: - - switch (source_desc->reference.class) { - case ACPI_REFCLASS_TABLE: /* This is a ddb_handle */ - case ACPI_REFCLASS_REFOF: - case ACPI_REFCLASS_INDEX: - - /* Return an additional reference to the object */ - - obj_desc = source_desc; - acpi_ut_add_reference(obj_desc); - break; - - default: - /* No named references are allowed here */ - - ACPI_ERROR((AE_INFO, - "Unsupported Reference type %X", - source_desc->reference.class)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - break; - - default: - - /* Default case is for unknown types */ - - ACPI_ERROR((AE_INFO, - "Node %p - Unknown object type %X", - node, entry_type)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - - } /* switch (entry_type) */ - - /* Return the object descriptor */ - - *object_ptr = (void *)obj_desc; - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c deleted file mode 100644 index 42adde01bc93..000000000000 --- a/drivers/acpi/executer/exresolv.c +++ /dev/null @@ -1,551 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exresolv - AML Interpreter object resolution - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exresolv") - -/* Local prototypes */ -static acpi_status -acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, - struct acpi_walk_state *walk_state); - -/******************************************************************************* - * - * FUNCTION: acpi_ex_resolve_to_value - * - * PARAMETERS: **stack_ptr - Points to entry on obj_stack, which can - * be either an (union acpi_operand_object *) - * or an acpi_handle. - * walk_state - Current method state - * - * RETURN: Status - * - * DESCRIPTION: Convert Reference objects to values - * - ******************************************************************************/ - -acpi_status -acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr); - - if (!stack_ptr || !*stack_ptr) { - ACPI_ERROR((AE_INFO, "Internal - null pointer")); - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - /* - * The entity pointed to by the stack_ptr can be either - * 1) A valid union acpi_operand_object, or - * 2) A struct acpi_namespace_node (named_obj) - */ - if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) { - status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (!*stack_ptr) { - ACPI_ERROR((AE_INFO, "Internal - null pointer")); - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - } - - /* - * Object on the stack may have changed if acpi_ex_resolve_object_to_value() - * was called (i.e., we can't use an _else_ here.) - */ - if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) { - status = - acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR - (struct acpi_namespace_node, - stack_ptr), walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr)); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_resolve_object_to_value - * - * PARAMETERS: stack_ptr - Pointer to an internal object - * walk_state - Current method state - * - * RETURN: Status - * - * DESCRIPTION: Retrieve the value from an internal object. The Reference type - * uses the associated AML opcode to determine the value. - * - ******************************************************************************/ - -static acpi_status -acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, - struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - union acpi_operand_object *stack_desc; - union acpi_operand_object *obj_desc = NULL; - u8 ref_type; - - ACPI_FUNCTION_TRACE(ex_resolve_object_to_value); - - stack_desc = *stack_ptr; - - /* This is an union acpi_operand_object */ - - switch (ACPI_GET_OBJECT_TYPE(stack_desc)) { - case ACPI_TYPE_LOCAL_REFERENCE: - - ref_type = stack_desc->reference.class; - - switch (ref_type) { - case ACPI_REFCLASS_LOCAL: - case ACPI_REFCLASS_ARG: - - /* - * Get the local from the method's state info - * Note: this increments the local's object reference count - */ - status = acpi_ds_method_data_get_value(ref_type, - stack_desc-> - reference.value, - walk_state, - &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Arg/Local %X] ValueObj is %p\n", - stack_desc->reference.value, - obj_desc)); - - /* - * Now we can delete the original Reference Object and - * replace it with the resolved value - */ - acpi_ut_remove_reference(stack_desc); - *stack_ptr = obj_desc; - break; - - case ACPI_REFCLASS_INDEX: - - switch (stack_desc->reference.target_type) { - case ACPI_TYPE_BUFFER_FIELD: - - /* Just return - do not dereference */ - break; - - case ACPI_TYPE_PACKAGE: - - /* If method call or copy_object - do not dereference */ - - if ((walk_state->opcode == - AML_INT_METHODCALL_OP) - || (walk_state->opcode == AML_COPY_OP)) { - break; - } - - /* Otherwise, dereference the package_index to a package element */ - - obj_desc = *stack_desc->reference.where; - if (obj_desc) { - /* - * Valid object descriptor, copy pointer to return value - * (i.e., dereference the package index) - * Delete the ref object, increment the returned object - */ - acpi_ut_remove_reference(stack_desc); - acpi_ut_add_reference(obj_desc); - *stack_ptr = obj_desc; - } else { - /* - * A NULL object descriptor means an uninitialized element of - * the package, can't dereference it - */ - ACPI_ERROR((AE_INFO, - "Attempt to dereference an Index to NULL package element Idx=%p", - stack_desc)); - status = AE_AML_UNINITIALIZED_ELEMENT; - } - break; - - default: - - /* Invalid reference object */ - - ACPI_ERROR((AE_INFO, - "Unknown TargetType %X in Index/Reference object %p", - stack_desc->reference.target_type, - stack_desc)); - status = AE_AML_INTERNAL; - break; - } - break; - - case ACPI_REFCLASS_REFOF: - case ACPI_REFCLASS_DEBUG: - case ACPI_REFCLASS_TABLE: - - /* Just leave the object as-is, do not dereference */ - - break; - - case ACPI_REFCLASS_NAME: /* Reference to a named object */ - - /* Dereference the name */ - - if ((stack_desc->reference.node->type == - ACPI_TYPE_DEVICE) - || (stack_desc->reference.node->type == - ACPI_TYPE_THERMAL)) { - - /* These node types do not have 'real' subobjects */ - - *stack_ptr = (void *)stack_desc->reference.node; - } else { - /* Get the object pointed to by the namespace node */ - - *stack_ptr = - (stack_desc->reference.node)->object; - acpi_ut_add_reference(*stack_ptr); - } - - acpi_ut_remove_reference(stack_desc); - break; - - default: - - ACPI_ERROR((AE_INFO, - "Unknown Reference type %X in %p", ref_type, - stack_desc)); - status = AE_AML_INTERNAL; - break; - } - break; - - case ACPI_TYPE_BUFFER: - - status = acpi_ds_get_buffer_arguments(stack_desc); - break; - - case ACPI_TYPE_PACKAGE: - - status = acpi_ds_get_package_arguments(stack_desc); - break; - - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "FieldRead SourceDesc=%p Type=%X\n", - stack_desc, - ACPI_GET_OBJECT_TYPE(stack_desc))); - - status = - acpi_ex_read_data_from_field(walk_state, stack_desc, - &obj_desc); - - /* Remove a reference to the original operand, then override */ - - acpi_ut_remove_reference(*stack_ptr); - *stack_ptr = (void *)obj_desc; - break; - - default: - break; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_resolve_multiple - * - * PARAMETERS: walk_state - Current state (contains AML opcode) - * Operand - Starting point for resolution - * return_type - Where the object type is returned - * return_desc - Where the resolved object is returned - * - * RETURN: Status - * - * DESCRIPTION: Return the base object and type. Traverse a reference list if - * necessary to get to the base object. - * - ******************************************************************************/ - -acpi_status -acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, - union acpi_operand_object *operand, - acpi_object_type * return_type, - union acpi_operand_object **return_desc) -{ - union acpi_operand_object *obj_desc = (void *)operand; - struct acpi_namespace_node *node; - acpi_object_type type; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple); - - /* Operand can be either a namespace node or an operand descriptor */ - - switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { - case ACPI_DESC_TYPE_OPERAND: - type = obj_desc->common.type; - break; - - case ACPI_DESC_TYPE_NAMED: - type = ((struct acpi_namespace_node *)obj_desc)->type; - obj_desc = - acpi_ns_get_attached_object((struct acpi_namespace_node *) - obj_desc); - - /* If we had an Alias node, use the attached object for type info */ - - if (type == ACPI_TYPE_LOCAL_ALIAS) { - type = ((struct acpi_namespace_node *)obj_desc)->type; - obj_desc = - acpi_ns_get_attached_object((struct - acpi_namespace_node *) - obj_desc); - } - break; - - default: - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* If type is anything other than a reference, we are done */ - - if (type != ACPI_TYPE_LOCAL_REFERENCE) { - goto exit; - } - - /* - * For reference objects created via the ref_of, Index, or Load/load_table - * operators, we need to get to the base object (as per the ACPI - * specification of the object_type and size_of operators). This means - * traversing the list of possibly many nested references. - */ - while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { - switch (obj_desc->reference.class) { - case ACPI_REFCLASS_REFOF: - case ACPI_REFCLASS_NAME: - - /* Dereference the reference pointer */ - - if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) { - node = obj_desc->reference.object; - } else { /* AML_INT_NAMEPATH_OP */ - - node = obj_desc->reference.node; - } - - /* All "References" point to a NS node */ - - if (ACPI_GET_DESCRIPTOR_TYPE(node) != - ACPI_DESC_TYPE_NAMED) { - ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]", - node, - acpi_ut_get_descriptor_name(node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - /* Get the attached object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - - /* No object, use the NS node type */ - - type = acpi_ns_get_type(node); - goto exit; - } - - /* Check for circular references */ - - if (obj_desc == operand) { - return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE); - } - break; - - case ACPI_REFCLASS_INDEX: - - /* Get the type of this reference (index into another object) */ - - type = obj_desc->reference.target_type; - if (type != ACPI_TYPE_PACKAGE) { - goto exit; - } - - /* - * The main object is a package, we want to get the type - * of the individual package element that is referenced by - * the index. - * - * This could of course in turn be another reference object. - */ - obj_desc = *(obj_desc->reference.where); - if (!obj_desc) { - - /* NULL package elements are allowed */ - - type = 0; /* Uninitialized */ - goto exit; - } - break; - - case ACPI_REFCLASS_TABLE: - - type = ACPI_TYPE_DDB_HANDLE; - goto exit; - - case ACPI_REFCLASS_LOCAL: - case ACPI_REFCLASS_ARG: - - if (return_desc) { - status = - acpi_ds_method_data_get_value(obj_desc-> - reference. - class, - obj_desc-> - reference. - value, - walk_state, - &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - acpi_ut_remove_reference(obj_desc); - } else { - status = - acpi_ds_method_data_get_node(obj_desc-> - reference. - class, - obj_desc-> - reference. - value, - walk_state, - &node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - type = ACPI_TYPE_ANY; - goto exit; - } - } - break; - - case ACPI_REFCLASS_DEBUG: - - /* The Debug Object is of type "DebugObject" */ - - type = ACPI_TYPE_DEBUG_OBJECT; - goto exit; - - default: - - ACPI_ERROR((AE_INFO, - "Unknown Reference Class %2.2X", - obj_desc->reference.class)); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - } - - /* - * Now we are guaranteed to have an object that has not been created - * via the ref_of or Index operators. - */ - type = ACPI_GET_OBJECT_TYPE(obj_desc); - - exit: - /* Convert internal types to external types */ - - switch (type) { - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - type = ACPI_TYPE_FIELD_UNIT; - break; - - case ACPI_TYPE_LOCAL_SCOPE: - - /* Per ACPI Specification, Scope is untyped */ - - type = ACPI_TYPE_ANY; - break; - - default: - /* No change to Type required */ - break; - } - - *return_type = type; - if (return_desc) { - *return_desc = obj_desc; - } - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c deleted file mode 100644 index 7602eaf5c479..000000000000 --- a/drivers/acpi/executer/exresop.c +++ /dev/null @@ -1,701 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exresop - AML Interpreter operand/object resolution - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exresop") - -/* Local prototypes */ -static acpi_status -acpi_ex_check_object_type(acpi_object_type type_needed, - acpi_object_type this_type, void *object); - -/******************************************************************************* - * - * FUNCTION: acpi_ex_check_object_type - * - * PARAMETERS: type_needed Object type needed - * this_type Actual object type - * Object Object pointer - * - * RETURN: Status - * - * DESCRIPTION: Check required type against actual type - * - ******************************************************************************/ - -static acpi_status -acpi_ex_check_object_type(acpi_object_type type_needed, - acpi_object_type this_type, void *object) -{ - ACPI_FUNCTION_ENTRY(); - - if (type_needed == ACPI_TYPE_ANY) { - - /* All types OK, so we don't perform any typechecks */ - - return (AE_OK); - } - - if (type_needed == ACPI_TYPE_LOCAL_REFERENCE) { - /* - * Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference - * objects and thus allow them to be targets. (As per the ACPI - * specification, a store to a constant is a noop.) - */ - if ((this_type == ACPI_TYPE_INTEGER) && - (((union acpi_operand_object *)object)->common. - flags & AOPOBJ_AML_CONSTANT)) { - return (AE_OK); - } - } - - if (type_needed != this_type) { - ACPI_ERROR((AE_INFO, - "Needed type [%s], found [%s] %p", - acpi_ut_get_type_name(type_needed), - acpi_ut_get_type_name(this_type), object)); - - return (AE_AML_OPERAND_TYPE); - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_resolve_operands - * - * PARAMETERS: Opcode - Opcode being interpreted - * stack_ptr - Pointer to the operand stack to be - * resolved - * walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Convert multiple input operands to the types required by the - * target operator. - * - * Each 5-bit group in arg_types represents one required - * operand and indicates the required Type. The corresponding operand - * will be converted to the required type if possible, otherwise we - * abort with an exception. - * - ******************************************************************************/ - -acpi_status -acpi_ex_resolve_operands(u16 opcode, - union acpi_operand_object ** stack_ptr, - struct acpi_walk_state * walk_state) -{ - union acpi_operand_object *obj_desc; - acpi_status status = AE_OK; - u8 object_type; - u32 arg_types; - const struct acpi_opcode_info *op_info; - u32 this_arg_type; - acpi_object_type type_needed; - u16 target_op = 0; - - ACPI_FUNCTION_TRACE_U32(ex_resolve_operands, opcode); - - op_info = acpi_ps_get_opcode_info(opcode); - if (op_info->class == AML_CLASS_UNKNOWN) { - return_ACPI_STATUS(AE_AML_BAD_OPCODE); - } - - arg_types = op_info->runtime_args; - if (arg_types == ARGI_INVALID_OPCODE) { - ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", opcode)); - - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Opcode %X [%s] RequiredOperandTypes=%8.8X\n", - opcode, op_info->name, arg_types)); - - /* - * Normal exit is with (arg_types == 0) at end of argument list. - * Function will return an exception from within the loop upon - * finding an entry which is not (or cannot be converted - * to) the required type; if stack underflows; or upon - * finding a NULL stack entry (which should not happen). - */ - while (GET_CURRENT_ARG_TYPE(arg_types)) { - if (!stack_ptr || !*stack_ptr) { - ACPI_ERROR((AE_INFO, "Null stack entry at %p", - stack_ptr)); - - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - /* Extract useful items */ - - obj_desc = *stack_ptr; - - /* Decode the descriptor type */ - - switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { - case ACPI_DESC_TYPE_NAMED: - - /* Namespace Node */ - - object_type = - ((struct acpi_namespace_node *)obj_desc)->type; - - /* - * Resolve an alias object. The construction of these objects - * guarantees that there is only one level of alias indirection; - * thus, the attached object is always the aliased namespace node - */ - if (object_type == ACPI_TYPE_LOCAL_ALIAS) { - obj_desc = - acpi_ns_get_attached_object((struct - acpi_namespace_node - *)obj_desc); - *stack_ptr = obj_desc; - object_type = - ((struct acpi_namespace_node *)obj_desc)-> - type; - } - break; - - case ACPI_DESC_TYPE_OPERAND: - - /* ACPI internal object */ - - object_type = ACPI_GET_OBJECT_TYPE(obj_desc); - - /* Check for bad acpi_object_type */ - - if (!acpi_ut_valid_object_type(object_type)) { - ACPI_ERROR((AE_INFO, - "Bad operand object type [%X]", - object_type)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) { - - /* Validate the Reference */ - - switch (obj_desc->reference.class) { - case ACPI_REFCLASS_DEBUG: - - target_op = AML_DEBUG_OP; - - /*lint -fallthrough */ - - case ACPI_REFCLASS_ARG: - case ACPI_REFCLASS_LOCAL: - case ACPI_REFCLASS_INDEX: - case ACPI_REFCLASS_REFOF: - case ACPI_REFCLASS_TABLE: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */ - case ACPI_REFCLASS_NAME: /* Reference to a named object */ - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Operand is a Reference, Class [%s] %2.2X\n", - acpi_ut_get_reference_name - (obj_desc), - obj_desc->reference. - class)); - break; - - default: - - ACPI_ERROR((AE_INFO, - "Unknown Reference Class %2.2X in %p", - obj_desc->reference.class, - obj_desc)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - } - break; - - default: - - /* Invalid descriptor */ - - ACPI_ERROR((AE_INFO, "Invalid descriptor %p [%s]", - obj_desc, - acpi_ut_get_descriptor_name(obj_desc))); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* Get one argument type, point to the next */ - - this_arg_type = GET_CURRENT_ARG_TYPE(arg_types); - INCREMENT_ARG_LIST(arg_types); - - /* - * Handle cases where the object does not need to be - * resolved to a value - */ - switch (this_arg_type) { - case ARGI_REF_OR_STRING: /* Can be a String or Reference */ - - if ((ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == - ACPI_DESC_TYPE_OPERAND) - && (ACPI_GET_OBJECT_TYPE(obj_desc) == - ACPI_TYPE_STRING)) { - /* - * String found - the string references a named object and - * must be resolved to a node - */ - goto next_operand; - } - - /* - * Else not a string - fall through to the normal Reference - * case below - */ - /*lint -fallthrough */ - - case ARGI_REFERENCE: /* References: */ - case ARGI_INTEGER_REF: - case ARGI_OBJECT_REF: - case ARGI_DEVICE_REF: - case ARGI_TARGETREF: /* Allows implicit conversion rules before store */ - case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ - case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ - - /* - * Need an operand of type ACPI_TYPE_LOCAL_REFERENCE - * A Namespace Node is OK as-is - */ - if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == - ACPI_DESC_TYPE_NAMED) { - goto next_operand; - } - - status = - acpi_ex_check_object_type(ACPI_TYPE_LOCAL_REFERENCE, - object_type, obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - goto next_operand; - - case ARGI_DATAREFOBJ: /* Store operator only */ - - /* - * We don't want to resolve index_op reference objects during - * a store because this would be an implicit de_ref_of operation. - * Instead, we just want to store the reference object. - * -- All others must be resolved below. - */ - if ((opcode == AML_STORE_OP) && - (ACPI_GET_OBJECT_TYPE(*stack_ptr) == - ACPI_TYPE_LOCAL_REFERENCE) - && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) { - goto next_operand; - } - break; - - default: - /* All cases covered above */ - break; - } - - /* - * Resolve this object to a value - */ - status = acpi_ex_resolve_to_value(stack_ptr, walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get the resolved object */ - - obj_desc = *stack_ptr; - - /* - * Check the resulting object (value) type - */ - switch (this_arg_type) { - /* - * For the simple cases, only one type of resolved object - * is allowed - */ - case ARGI_MUTEX: - - /* Need an operand of type ACPI_TYPE_MUTEX */ - - type_needed = ACPI_TYPE_MUTEX; - break; - - case ARGI_EVENT: - - /* Need an operand of type ACPI_TYPE_EVENT */ - - type_needed = ACPI_TYPE_EVENT; - break; - - case ARGI_PACKAGE: /* Package */ - - /* Need an operand of type ACPI_TYPE_PACKAGE */ - - type_needed = ACPI_TYPE_PACKAGE; - break; - - case ARGI_ANYTYPE: - - /* Any operand type will do */ - - type_needed = ACPI_TYPE_ANY; - break; - - case ARGI_DDBHANDLE: - - /* Need an operand of type ACPI_TYPE_DDB_HANDLE */ - - type_needed = ACPI_TYPE_LOCAL_REFERENCE; - break; - - /* - * The more complex cases allow multiple resolved object types - */ - case ARGI_INTEGER: - - /* - * Need an operand of type ACPI_TYPE_INTEGER, - * But we can implicitly convert from a STRING or BUFFER - * Aka - "Implicit Source Operand Conversion" - */ - status = - acpi_ex_convert_to_integer(obj_desc, stack_ptr, 16); - if (ACPI_FAILURE(status)) { - if (status == AE_TYPE) { - ACPI_ERROR((AE_INFO, - "Needed [Integer/String/Buffer], found [%s] %p", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - return_ACPI_STATUS(status); - } - - if (obj_desc != *stack_ptr) { - acpi_ut_remove_reference(obj_desc); - } - goto next_operand; - - case ARGI_BUFFER: - - /* - * Need an operand of type ACPI_TYPE_BUFFER, - * But we can implicitly convert from a STRING or INTEGER - * Aka - "Implicit Source Operand Conversion" - */ - status = acpi_ex_convert_to_buffer(obj_desc, stack_ptr); - if (ACPI_FAILURE(status)) { - if (status == AE_TYPE) { - ACPI_ERROR((AE_INFO, - "Needed [Integer/String/Buffer], found [%s] %p", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - return_ACPI_STATUS(status); - } - - if (obj_desc != *stack_ptr) { - acpi_ut_remove_reference(obj_desc); - } - goto next_operand; - - case ARGI_STRING: - - /* - * Need an operand of type ACPI_TYPE_STRING, - * But we can implicitly convert from a BUFFER or INTEGER - * Aka - "Implicit Source Operand Conversion" - */ - status = acpi_ex_convert_to_string(obj_desc, stack_ptr, - ACPI_IMPLICIT_CONVERT_HEX); - if (ACPI_FAILURE(status)) { - if (status == AE_TYPE) { - ACPI_ERROR((AE_INFO, - "Needed [Integer/String/Buffer], found [%s] %p", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - return_ACPI_STATUS(status); - } - - if (obj_desc != *stack_ptr) { - acpi_ut_remove_reference(obj_desc); - } - goto next_operand; - - case ARGI_COMPUTEDATA: - - /* Need an operand of type INTEGER, STRING or BUFFER */ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - - /* Valid operand */ - break; - - default: - ACPI_ERROR((AE_INFO, - "Needed [Integer/String/Buffer], found [%s] %p", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - goto next_operand; - - case ARGI_BUFFER_OR_STRING: - - /* Need an operand of type STRING or BUFFER */ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - - /* Valid operand */ - break; - - case ACPI_TYPE_INTEGER: - - /* Highest priority conversion is to type Buffer */ - - status = - acpi_ex_convert_to_buffer(obj_desc, - stack_ptr); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (obj_desc != *stack_ptr) { - acpi_ut_remove_reference(obj_desc); - } - break; - - default: - ACPI_ERROR((AE_INFO, - "Needed [Integer/String/Buffer], found [%s] %p", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - goto next_operand; - - case ARGI_DATAOBJECT: - /* - * ARGI_DATAOBJECT is only used by the size_of operator. - * Need a buffer, string, package, or ref_of reference. - * - * The only reference allowed here is a direct reference to - * a namespace node. - */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_PACKAGE: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - case ACPI_TYPE_LOCAL_REFERENCE: - - /* Valid operand */ - break; - - default: - ACPI_ERROR((AE_INFO, - "Needed [Buffer/String/Package/Reference], found [%s] %p", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - goto next_operand; - - case ARGI_COMPLEXOBJ: - - /* Need a buffer or package or (ACPI 2.0) String */ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_PACKAGE: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - - /* Valid operand */ - break; - - default: - ACPI_ERROR((AE_INFO, - "Needed [Buffer/String/Package], found [%s] %p", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - goto next_operand; - - case ARGI_REGION_OR_BUFFER: /* Used by Load() only */ - - /* Need an operand of type REGION or a BUFFER (which could be a resolved region field) */ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_BUFFER: - case ACPI_TYPE_REGION: - - /* Valid operand */ - break; - - default: - ACPI_ERROR((AE_INFO, - "Needed [Region/Buffer], found [%s] %p", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - goto next_operand; - - case ARGI_DATAREFOBJ: - - /* Used by the Store() operator only */ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_PACKAGE: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_REFERENCE: - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - case ACPI_TYPE_DDB_HANDLE: - - /* Valid operand */ - break; - - default: - - if (acpi_gbl_enable_interpreter_slack) { - /* - * Enable original behavior of Store(), allowing any and all - * objects as the source operand. The ACPI spec does not - * allow this, however. - */ - break; - } - - if (target_op == AML_DEBUG_OP) { - - /* Allow store of any object to the Debug object */ - - break; - } - - ACPI_ERROR((AE_INFO, - "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - goto next_operand; - - default: - - /* Unknown type */ - - ACPI_ERROR((AE_INFO, - "Internal - Unknown ARGI (required operand) type %X", - this_arg_type)); - - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* - * Make sure that the original object was resolved to the - * required object type (Simple cases only). - */ - status = acpi_ex_check_object_type(type_needed, - ACPI_GET_OBJECT_TYPE - (*stack_ptr), *stack_ptr); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - next_operand: - /* - * If more operands needed, decrement stack_ptr to point - * to next operand on stack - */ - if (GET_CURRENT_ARG_TYPE(arg_types)) { - stack_ptr--; - } - } - - ACPI_DUMP_OPERANDS(walk_state->operands, - acpi_ps_get_opcode_name(opcode), - walk_state->num_operands); - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c deleted file mode 100644 index 6f5647fdc006..000000000000 --- a/drivers/acpi/executer/exstore.c +++ /dev/null @@ -1,716 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exstore - AML Interpreter object store support - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exstore") - -/* Local prototypes */ -static void -acpi_ex_do_debug_object(union acpi_operand_object *source_desc, - u32 level, u32 index); - -static acpi_status -acpi_ex_store_object_to_index(union acpi_operand_object *val_desc, - union acpi_operand_object *dest_desc, - struct acpi_walk_state *walk_state); - -/******************************************************************************* - * - * FUNCTION: acpi_ex_do_debug_object - * - * PARAMETERS: source_desc - Value to be stored - * Level - Indentation level (used for packages) - * Index - Current package element, zero if not pkg - * - * RETURN: None - * - * DESCRIPTION: Handles stores to the Debug Object. - * - ******************************************************************************/ - -static void -acpi_ex_do_debug_object(union acpi_operand_object *source_desc, - u32 level, u32 index) -{ - u32 i; - - ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); - - /* Print line header as long as we are not in the middle of an object display */ - - if (!((level > 0) && index == 0)) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", - level, " ")); - } - - /* Display index for package output only */ - - if (index > 0) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - "(%.2u) ", index - 1)); - } - - if (!source_desc) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Null Object]\n")); - return_VOID; - } - - if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s ", - acpi_ut_get_object_type_name - (source_desc))); - - if (!acpi_ut_valid_internal_object(source_desc)) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - "%p, Invalid Internal Object!\n", - source_desc)); - return_VOID; - } - } else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == - ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: %p\n", - acpi_ut_get_type_name(((struct - acpi_namespace_node - *)source_desc)-> - type), - source_desc)); - return_VOID; - } else { - return_VOID; - } - - /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ - - switch (ACPI_GET_OBJECT_TYPE(source_desc)) { - case ACPI_TYPE_INTEGER: - - /* Output correct integer width */ - - if (acpi_gbl_integer_byte_width == 4) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n", - (u32) source_desc->integer. - value)); - } else { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - "0x%8.8X%8.8X\n", - ACPI_FORMAT_UINT64(source_desc-> - integer. - value))); - } - break; - - case ACPI_TYPE_BUFFER: - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]\n", - (u32) source_desc->buffer.length)); - ACPI_DUMP_BUFFER(source_desc->buffer.pointer, - (source_desc->buffer.length < - 256) ? source_desc->buffer.length : 256); - break; - - case ACPI_TYPE_STRING: - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n", - source_desc->string.length, - source_desc->string.pointer)); - break; - - case ACPI_TYPE_PACKAGE: - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - "[Contains 0x%.2X Elements]\n", - source_desc->package.count)); - - /* Output the entire contents of the package */ - - for (i = 0; i < source_desc->package.count; i++) { - acpi_ex_do_debug_object(source_desc->package. - elements[i], level + 4, i + 1); - } - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s] ", - acpi_ut_get_reference_name(source_desc))); - - /* Decode the reference */ - - switch (source_desc->reference.class) { - case ACPI_REFCLASS_INDEX: - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%X\n", - source_desc->reference.value)); - break; - - case ACPI_REFCLASS_TABLE: - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - "Table Index 0x%X\n", - source_desc->reference.value)); - break; - - default: - break; - } - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " ")); - - /* Check for valid node first, then valid object */ - - if (source_desc->reference.node) { - if (ACPI_GET_DESCRIPTOR_TYPE - (source_desc->reference.node) != - ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - " %p - Not a valid namespace node\n", - source_desc->reference. - node)); - } else { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, - "Node %p [%4.4s] ", - source_desc->reference. - node, - (source_desc->reference. - node)->name.ascii)); - - switch ((source_desc->reference.node)->type) { - - /* These types have no attached object */ - - case ACPI_TYPE_DEVICE: - acpi_os_printf("Device\n"); - break; - - case ACPI_TYPE_THERMAL: - acpi_os_printf("Thermal Zone\n"); - break; - - default: - acpi_ex_do_debug_object((source_desc-> - reference. - node)->object, - level + 4, 0); - break; - } - } - } else if (source_desc->reference.object) { - if (ACPI_GET_DESCRIPTOR_TYPE - (source_desc->reference.object) == - ACPI_DESC_TYPE_NAMED) { - acpi_ex_do_debug_object(((struct - acpi_namespace_node *) - source_desc->reference. - object)->object, - level + 4, 0); - } else { - acpi_ex_do_debug_object(source_desc->reference. - object, level + 4, 0); - } - } - break; - - default: - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p\n", - source_desc)); - break; - } - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n")); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_store - * - * PARAMETERS: *source_desc - Value to be stored - * *dest_desc - Where to store it. Must be an NS node - * or an union acpi_operand_object of type - * Reference; - * walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Store the value described by source_desc into the location - * described by dest_desc. Called by various interpreter - * functions to store the result of an operation into - * the destination operand -- not just simply the actual "Store" - * ASL operator. - * - ******************************************************************************/ - -acpi_status -acpi_ex_store(union acpi_operand_object *source_desc, - union acpi_operand_object *dest_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - union acpi_operand_object *ref_desc = dest_desc; - - ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc); - - /* Validate parameters */ - - if (!source_desc || !dest_desc) { - ACPI_ERROR((AE_INFO, "Null parameter")); - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - /* dest_desc can be either a namespace node or an ACPI object */ - - if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) { - /* - * Dest is a namespace node, - * Storing an object into a Named node. - */ - status = acpi_ex_store_object_to_node(source_desc, - (struct - acpi_namespace_node *) - dest_desc, walk_state, - ACPI_IMPLICIT_CONVERSION); - - return_ACPI_STATUS(status); - } - - /* Destination object must be a Reference or a Constant object */ - - switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { - case ACPI_TYPE_LOCAL_REFERENCE: - break; - - case ACPI_TYPE_INTEGER: - - /* Allow stores to Constants -- a Noop as per ACPI spec */ - - if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) { - return_ACPI_STATUS(AE_OK); - } - - /*lint -fallthrough */ - - default: - - /* Destination is not a Reference object */ - - ACPI_ERROR((AE_INFO, - "Target is not a Reference or Constant object - %s [%p]", - acpi_ut_get_object_type_name(dest_desc), - dest_desc)); - - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* - * Examine the Reference class. These cases are handled: - * - * 1) Store to Name (Change the object associated with a name) - * 2) Store to an indexed area of a Buffer or Package - * 3) Store to a Method Local or Arg - * 4) Store to the debug object - */ - switch (ref_desc->reference.class) { - case ACPI_REFCLASS_REFOF: - - /* Storing an object into a Name "container" */ - - status = acpi_ex_store_object_to_node(source_desc, - ref_desc->reference. - object, walk_state, - ACPI_IMPLICIT_CONVERSION); - break; - - case ACPI_REFCLASS_INDEX: - - /* Storing to an Index (pointer into a packager or buffer) */ - - status = - acpi_ex_store_object_to_index(source_desc, ref_desc, - walk_state); - break; - - case ACPI_REFCLASS_LOCAL: - case ACPI_REFCLASS_ARG: - - /* Store to a method local/arg */ - - status = - acpi_ds_store_object_to_local(ref_desc->reference.class, - ref_desc->reference.value, - source_desc, walk_state); - break; - - case ACPI_REFCLASS_DEBUG: - - /* - * Storing to the Debug object causes the value stored to be - * displayed and otherwise has no effect -- see ACPI Specification - */ - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "**** Write to Debug Object: Object %p %s ****:\n\n", - source_desc, - acpi_ut_get_object_type_name(source_desc))); - - acpi_ex_do_debug_object(source_desc, 0, 0); - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown Reference Class %2.2X", - ref_desc->reference.class)); - ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO); - - status = AE_AML_INTERNAL; - break; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_store_object_to_index - * - * PARAMETERS: *source_desc - Value to be stored - * *dest_desc - Named object to receive the value - * walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Store the object to indexed Buffer or Package element - * - ******************************************************************************/ - -static acpi_status -acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, - union acpi_operand_object *index_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - union acpi_operand_object *obj_desc; - union acpi_operand_object *new_desc; - u8 value = 0; - u32 i; - - ACPI_FUNCTION_TRACE(ex_store_object_to_index); - - /* - * Destination must be a reference pointer, and - * must point to either a buffer or a package - */ - switch (index_desc->reference.target_type) { - case ACPI_TYPE_PACKAGE: - /* - * Storing to a package element. Copy the object and replace - * any existing object with the new object. No implicit - * conversion is performed. - * - * The object at *(index_desc->Reference.Where) is the - * element within the package that is to be modified. - * The parent package object is at index_desc->Reference.Object - */ - obj_desc = *(index_desc->reference.where); - - if (ACPI_GET_OBJECT_TYPE(source_desc) == - ACPI_TYPE_LOCAL_REFERENCE - && source_desc->reference.class == ACPI_REFCLASS_TABLE) { - - /* This is a DDBHandle, just add a reference to it */ - - acpi_ut_add_reference(source_desc); - new_desc = source_desc; - } else { - /* Normal object, copy it */ - - status = - acpi_ut_copy_iobject_to_iobject(source_desc, - &new_desc, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - if (obj_desc) { - - /* Decrement reference count by the ref count of the parent package */ - - for (i = 0; i < ((union acpi_operand_object *) - index_desc->reference.object)->common. - reference_count; i++) { - acpi_ut_remove_reference(obj_desc); - } - } - - *(index_desc->reference.where) = new_desc; - - /* Increment ref count by the ref count of the parent package-1 */ - - for (i = 1; i < ((union acpi_operand_object *) - index_desc->reference.object)->common. - reference_count; i++) { - acpi_ut_add_reference(new_desc); - } - - break; - - case ACPI_TYPE_BUFFER_FIELD: - - /* - * Store into a Buffer or String (not actually a real buffer_field) - * at a location defined by an Index. - * - * The first 8-bit element of the source object is written to the - * 8-bit Buffer location defined by the Index destination object, - * according to the ACPI 2.0 specification. - */ - - /* - * Make sure the target is a Buffer or String. An error should - * not happen here, since the reference_object was constructed - * by the INDEX_OP code. - */ - obj_desc = index_desc->reference.object; - if ((ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_BUFFER) && - (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_STRING)) { - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* - * The assignment of the individual elements will be slightly - * different for each source type. - */ - switch (ACPI_GET_OBJECT_TYPE(source_desc)) { - case ACPI_TYPE_INTEGER: - - /* Use the least-significant byte of the integer */ - - value = (u8) (source_desc->integer.value); - break; - - case ACPI_TYPE_BUFFER: - case ACPI_TYPE_STRING: - - /* Note: Takes advantage of common string/buffer fields */ - - value = source_desc->buffer.pointer[0]; - break; - - default: - - /* All other types are invalid */ - - ACPI_ERROR((AE_INFO, - "Source must be Integer/Buffer/String type, not %s", - acpi_ut_get_object_type_name(source_desc))); - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* Store the source value into the target buffer byte */ - - obj_desc->buffer.pointer[index_desc->reference.value] = value; - break; - - default: - ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField")); - status = AE_AML_OPERAND_TYPE; - break; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_store_object_to_node - * - * PARAMETERS: source_desc - Value to be stored - * Node - Named object to receive the value - * walk_state - Current walk state - * implicit_conversion - Perform implicit conversion (yes/no) - * - * RETURN: Status - * - * DESCRIPTION: Store the object to the named object. - * - * The Assignment of an object to a named object is handled here - * The value passed in will replace the current value (if any) - * with the input value. - * - * When storing into an object the data is converted to the - * target object type then stored in the object. This means - * that the target object type (for an initialized target) will - * not be changed by a store operation. - * - * Assumes parameters are already validated. - * - ******************************************************************************/ - -acpi_status -acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, - struct acpi_namespace_node *node, - struct acpi_walk_state *walk_state, - u8 implicit_conversion) -{ - acpi_status status = AE_OK; - union acpi_operand_object *target_desc; - union acpi_operand_object *new_desc; - acpi_object_type target_type; - - ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc); - - /* Get current type of the node, and object attached to Node */ - - target_type = acpi_ns_get_type(node); - target_desc = acpi_ns_get_attached_object(node); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", - source_desc, - acpi_ut_get_object_type_name(source_desc), node, - acpi_ut_get_type_name(target_type))); - - /* - * Resolve the source object to an actual value - * (If it is a reference object) - */ - status = acpi_ex_resolve_object(&source_desc, target_type, walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* If no implicit conversion, drop into the default case below */ - - if ((!implicit_conversion) || - ((walk_state->opcode == AML_COPY_OP) && - (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && - (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && - (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { - /* - * Force execution of default (no implicit conversion). Note: - * copy_object does not perform an implicit conversion, as per the ACPI - * spec -- except in case of region/bank/index fields -- because these - * objects must retain their original type permanently. - */ - target_type = ACPI_TYPE_ANY; - } - - /* Do the actual store operation */ - - switch (target_type) { - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - /* For fields, copy the source data to the target field. */ - - status = acpi_ex_write_data_to_field(source_desc, target_desc, - &walk_state->result_obj); - break; - - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - - /* - * These target types are all of type Integer/String/Buffer, and - * therefore support implicit conversion before the store. - * - * Copy and/or convert the source object to a new target object - */ - status = - acpi_ex_store_object_to_object(source_desc, target_desc, - &new_desc, walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (new_desc != target_desc) { - /* - * Store the new new_desc as the new value of the Name, and set - * the Name's type to that of the value being stored in it. - * source_desc reference count is incremented by attach_object. - * - * Note: This may change the type of the node if an explicit store - * has been performed such that the node/object type has been - * changed. - */ - status = - acpi_ns_attach_object(node, new_desc, - new_desc->common.type); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Store %s into %s via Convert/Attach\n", - acpi_ut_get_object_type_name - (source_desc), - acpi_ut_get_object_type_name - (new_desc))); - } - break; - - default: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Storing %s (%p) directly into node (%p) with no implicit conversion\n", - acpi_ut_get_object_type_name(source_desc), - source_desc, node)); - - /* No conversions for all other types. Just attach the source object */ - - status = acpi_ns_attach_object(node, source_desc, - ACPI_GET_OBJECT_TYPE - (source_desc)); - break; - } - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c deleted file mode 100644 index ad2047afa463..000000000000 --- a/drivers/acpi/executer/exstoren.c +++ /dev/null @@ -1,304 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exstoren - AML Interpreter object store support, - * Store to Node (namespace object) - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exstoren") - -/******************************************************************************* - * - * FUNCTION: acpi_ex_resolve_object - * - * PARAMETERS: source_desc_ptr - Pointer to the source object - * target_type - Current type of the target - * walk_state - Current walk state - * - * RETURN: Status, resolved object in source_desc_ptr. - * - * DESCRIPTION: Resolve an object. If the object is a reference, dereference - * it and return the actual object in the source_desc_ptr. - * - ******************************************************************************/ -acpi_status -acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, - acpi_object_type target_type, - struct acpi_walk_state *walk_state) -{ - union acpi_operand_object *source_desc = *source_desc_ptr; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ex_resolve_object); - - /* Ensure we have a Target that can be stored to */ - - switch (target_type) { - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - /* - * These cases all require only Integers or values that - * can be converted to Integers (Strings or Buffers) - */ - - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - - /* - * Stores into a Field/Region or into a Integer/Buffer/String - * are all essentially the same. This case handles the - * "interchangeable" types Integer, String, and Buffer. - */ - if (ACPI_GET_OBJECT_TYPE(source_desc) == - ACPI_TYPE_LOCAL_REFERENCE) { - - /* Resolve a reference object first */ - - status = - acpi_ex_resolve_to_value(source_desc_ptr, - walk_state); - if (ACPI_FAILURE(status)) { - break; - } - } - - /* For copy_object, no further validation necessary */ - - if (walk_state->opcode == AML_COPY_OP) { - break; - } - - /* Must have a Integer, Buffer, or String */ - - if ((ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) && - (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) && - (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) && - !((ACPI_GET_OBJECT_TYPE(source_desc) == - ACPI_TYPE_LOCAL_REFERENCE) - && (source_desc->reference.class == - ACPI_REFCLASS_TABLE))) { - - /* Conversion successful but still not a valid type */ - - ACPI_ERROR((AE_INFO, - "Cannot assign type %s to %s (must be type Int/Str/Buf)", - acpi_ut_get_object_type_name(source_desc), - acpi_ut_get_type_name(target_type))); - status = AE_AML_OPERAND_TYPE; - } - break; - - case ACPI_TYPE_LOCAL_ALIAS: - case ACPI_TYPE_LOCAL_METHOD_ALIAS: - - /* - * All aliases should have been resolved earlier, during the - * operand resolution phase. - */ - ACPI_ERROR((AE_INFO, "Store into an unresolved Alias object")); - status = AE_AML_INTERNAL; - break; - - case ACPI_TYPE_PACKAGE: - default: - - /* - * All other types than Alias and the various Fields come here, - * including the untyped case - ACPI_TYPE_ANY. - */ - break; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_store_object_to_object - * - * PARAMETERS: source_desc - Object to store - * dest_desc - Object to receive a copy of the source - * new_desc - New object if dest_desc is obsoleted - * walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: "Store" an object to another object. This may include - * converting the source type to the target type (implicit - * conversion), and a copy of the value of the source to - * the target. - * - * The Assignment of an object to another (not named) object - * is handled here. - * The Source passed in will replace the current value (if any) - * with the input value. - * - * When storing into an object the data is converted to the - * target object type then stored in the object. This means - * that the target object type (for an initialized target) will - * not be changed by a store operation. - * - * This module allows destination types of Number, String, - * Buffer, and Package. - * - * Assumes parameters are already validated. NOTE: source_desc - * resolution (from a reference object) must be performed by - * the caller if necessary. - * - ******************************************************************************/ - -acpi_status -acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, - union acpi_operand_object *dest_desc, - union acpi_operand_object **new_desc, - struct acpi_walk_state *walk_state) -{ - union acpi_operand_object *actual_src_desc; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_object, source_desc); - - actual_src_desc = source_desc; - if (!dest_desc) { - /* - * There is no destination object (An uninitialized node or - * package element), so we can simply copy the source object - * creating a new destination object - */ - status = - acpi_ut_copy_iobject_to_iobject(actual_src_desc, new_desc, - walk_state); - return_ACPI_STATUS(status); - } - - if (ACPI_GET_OBJECT_TYPE(source_desc) != - ACPI_GET_OBJECT_TYPE(dest_desc)) { - /* - * The source type does not match the type of the destination. - * Perform the "implicit conversion" of the source to the current type - * of the target as per the ACPI specification. - * - * If no conversion performed, actual_src_desc = source_desc. - * Otherwise, actual_src_desc is a temporary object to hold the - * converted object. - */ - status = - acpi_ex_convert_to_target_type(ACPI_GET_OBJECT_TYPE - (dest_desc), source_desc, - &actual_src_desc, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (source_desc == actual_src_desc) { - /* - * No conversion was performed. Return the source_desc as the - * new object. - */ - *new_desc = source_desc; - return_ACPI_STATUS(AE_OK); - } - } - - /* - * We now have two objects of identical types, and we can perform a - * copy of the *value* of the source object. - */ - switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { - case ACPI_TYPE_INTEGER: - - dest_desc->integer.value = actual_src_desc->integer.value; - - /* Truncate value if we are executing from a 32-bit ACPI table */ - - acpi_ex_truncate_for32bit_table(dest_desc); - break; - - case ACPI_TYPE_STRING: - - status = - acpi_ex_store_string_to_string(actual_src_desc, dest_desc); - break; - - case ACPI_TYPE_BUFFER: - - status = - acpi_ex_store_buffer_to_buffer(actual_src_desc, dest_desc); - break; - - case ACPI_TYPE_PACKAGE: - - status = - acpi_ut_copy_iobject_to_iobject(actual_src_desc, &dest_desc, - walk_state); - break; - - default: - /* - * All other types come here. - */ - ACPI_WARNING((AE_INFO, "Store into type %s not implemented", - acpi_ut_get_object_type_name(dest_desc))); - - status = AE_NOT_IMPLEMENTED; - break; - } - - if (actual_src_desc != source_desc) { - - /* Delete the intermediate (temporary) source object */ - - acpi_ut_remove_reference(actual_src_desc); - } - - *new_desc = dest_desc; - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c deleted file mode 100644 index a48d580d71c2..000000000000 --- a/drivers/acpi/executer/exstorob.c +++ /dev/null @@ -1,209 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exstorob - AML Interpreter object store support, store to object - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exstorob") - -/******************************************************************************* - * - * FUNCTION: acpi_ex_store_buffer_to_buffer - * - * PARAMETERS: source_desc - Source object to copy - * target_desc - Destination object of the copy - * - * RETURN: Status - * - * DESCRIPTION: Copy a buffer object to another buffer object. - * - ******************************************************************************/ -acpi_status -acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, - union acpi_operand_object *target_desc) -{ - u32 length; - u8 *buffer; - - ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc); - - /* We know that source_desc is a buffer by now */ - - buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer); - length = source_desc->buffer.length; - - /* - * If target is a buffer of length zero or is a static buffer, - * allocate a new buffer of the proper length - */ - if ((target_desc->buffer.length == 0) || - (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) { - target_desc->buffer.pointer = ACPI_ALLOCATE(length); - if (!target_desc->buffer.pointer) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - target_desc->buffer.length = length; - } - - /* Copy source buffer to target buffer */ - - if (length <= target_desc->buffer.length) { - - /* Clear existing buffer and copy in the new one */ - - ACPI_MEMSET(target_desc->buffer.pointer, 0, - target_desc->buffer.length); - ACPI_MEMCPY(target_desc->buffer.pointer, buffer, length); - -#ifdef ACPI_OBSOLETE_BEHAVIOR - /* - * NOTE: ACPI versions up to 3.0 specified that the buffer must be - * truncated if the string is smaller than the buffer. However, "other" - * implementations of ACPI never did this and thus became the defacto - * standard. ACPI 3.0_a changes this behavior such that the buffer - * is no longer truncated. - */ - - /* - * OBSOLETE BEHAVIOR: - * If the original source was a string, we must truncate the buffer, - * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer - * copy must not truncate the original buffer. - */ - if (original_src_type == ACPI_TYPE_STRING) { - - /* Set the new length of the target */ - - target_desc->buffer.length = length; - } -#endif - } else { - /* Truncate the source, copy only what will fit */ - - ACPI_MEMCPY(target_desc->buffer.pointer, buffer, - target_desc->buffer.length); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Truncating source buffer from %X to %X\n", - length, target_desc->buffer.length)); - } - - /* Copy flags */ - - target_desc->buffer.flags = source_desc->buffer.flags; - target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_store_string_to_string - * - * PARAMETERS: source_desc - Source object to copy - * target_desc - Destination object of the copy - * - * RETURN: Status - * - * DESCRIPTION: Copy a String object to another String object - * - ******************************************************************************/ - -acpi_status -acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, - union acpi_operand_object *target_desc) -{ - u32 length; - u8 *buffer; - - ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc); - - /* We know that source_desc is a string by now */ - - buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer); - length = source_desc->string.length; - - /* - * Replace existing string value if it will fit and the string - * pointer is not a static pointer (part of an ACPI table) - */ - if ((length < target_desc->string.length) && - (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { - /* - * String will fit in existing non-static buffer. - * Clear old string and copy in the new one - */ - ACPI_MEMSET(target_desc->string.pointer, 0, - (acpi_size) target_desc->string.length + 1); - ACPI_MEMCPY(target_desc->string.pointer, buffer, length); - } else { - /* - * Free the current buffer, then allocate a new buffer - * large enough to hold the value - */ - if (target_desc->string.pointer && - (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { - - /* Only free if not a pointer into the DSDT */ - - ACPI_FREE(target_desc->string.pointer); - } - - target_desc->string.pointer = ACPI_ALLOCATE_ZEROED((acpi_size) - length + 1); - if (!target_desc->string.pointer) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; - ACPI_MEMCPY(target_desc->string.pointer, buffer, length); - } - - /* Set the new target length */ - - target_desc->string.length = length; - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c deleted file mode 100644 index a25b2c576eb1..000000000000 --- a/drivers/acpi/executer/exsystem.c +++ /dev/null @@ -1,303 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exsystem - Interface to OS services - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exsystem") - -/******************************************************************************* - * - * FUNCTION: acpi_ex_system_wait_semaphore - * - * PARAMETERS: Semaphore - Semaphore to wait on - * Timeout - Max time to wait - * - * RETURN: Status - * - * DESCRIPTION: Implements a semaphore wait with a check to see if the - * semaphore is available immediately. If it is not, the - * interpreter is released before waiting. - * - ******************************************************************************/ -acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); - - status = acpi_os_wait_semaphore(semaphore, 1, ACPI_DO_NOT_WAIT); - if (ACPI_SUCCESS(status)) { - return_ACPI_STATUS(status); - } - - if (status == AE_TIME) { - - /* We must wait, so unlock the interpreter */ - - acpi_ex_relinquish_interpreter(); - - status = acpi_os_wait_semaphore(semaphore, 1, timeout); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "*** Thread awake after blocking, %s\n", - acpi_format_exception(status))); - - /* Reacquire the interpreter */ - - acpi_ex_reacquire_interpreter(); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_system_wait_mutex - * - * PARAMETERS: Mutex - Mutex to wait on - * Timeout - Max time to wait - * - * RETURN: Status - * - * DESCRIPTION: Implements a mutex wait with a check to see if the - * mutex is available immediately. If it is not, the - * interpreter is released before waiting. - * - ******************************************************************************/ - -acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ex_system_wait_mutex); - - status = acpi_os_acquire_mutex(mutex, ACPI_DO_NOT_WAIT); - if (ACPI_SUCCESS(status)) { - return_ACPI_STATUS(status); - } - - if (status == AE_TIME) { - - /* We must wait, so unlock the interpreter */ - - acpi_ex_relinquish_interpreter(); - - status = acpi_os_acquire_mutex(mutex, timeout); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "*** Thread awake after blocking, %s\n", - acpi_format_exception(status))); - - /* Reacquire the interpreter */ - - acpi_ex_reacquire_interpreter(); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_system_do_stall - * - * PARAMETERS: how_long - The amount of time to stall, - * in microseconds - * - * RETURN: Status - * - * DESCRIPTION: Suspend running thread for specified amount of time. - * Note: ACPI specification requires that Stall() does not - * relinquish the processor, and delays longer than 100 usec - * should use Sleep() instead. We allow stalls up to 255 usec - * for compatibility with other interpreters and existing BIOSs. - * - ******************************************************************************/ - -acpi_status acpi_ex_system_do_stall(u32 how_long) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_ENTRY(); - - if (how_long > 255) { /* 255 microseconds */ - /* - * Longer than 255 usec, this is an error - * - * (ACPI specifies 100 usec as max, but this gives some slack in - * order to support existing BIOSs) - */ - ACPI_ERROR((AE_INFO, "Time parameter is too large (%d)", - how_long)); - status = AE_AML_OPERAND_VALUE; - } else { - acpi_os_stall(how_long); - } - - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_system_do_suspend - * - * PARAMETERS: how_long - The amount of time to suspend, - * in milliseconds - * - * RETURN: None - * - * DESCRIPTION: Suspend running thread for specified amount of time. - * - ******************************************************************************/ - -acpi_status acpi_ex_system_do_suspend(acpi_integer how_long) -{ - ACPI_FUNCTION_ENTRY(); - - /* Since this thread will sleep, we must release the interpreter */ - - acpi_ex_relinquish_interpreter(); - - acpi_os_sleep(how_long); - - /* And now we must get the interpreter again */ - - acpi_ex_reacquire_interpreter(); - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_system_signal_event - * - * PARAMETERS: obj_desc - The object descriptor for this op - * - * RETURN: Status - * - * DESCRIPTION: Provides an access point to perform synchronization operations - * within the AML. - * - ******************************************************************************/ - -acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ex_system_signal_event); - - if (obj_desc) { - status = - acpi_os_signal_semaphore(obj_desc->event.os_semaphore, 1); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_system_wait_event - * - * PARAMETERS: time_desc - The 'time to delay' object descriptor - * obj_desc - The object descriptor for this op - * - * RETURN: Status - * - * DESCRIPTION: Provides an access point to perform synchronization operations - * within the AML. This operation is a request to wait for an - * event. - * - ******************************************************************************/ - -acpi_status -acpi_ex_system_wait_event(union acpi_operand_object *time_desc, - union acpi_operand_object *obj_desc) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ex_system_wait_event); - - if (obj_desc) { - status = - acpi_ex_system_wait_semaphore(obj_desc->event.os_semaphore, - (u16) time_desc->integer. - value); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_system_reset_event - * - * PARAMETERS: obj_desc - The object descriptor for this op - * - * RETURN: Status - * - * DESCRIPTION: Reset an event to a known state. - * - ******************************************************************************/ - -acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc) -{ - acpi_status status = AE_OK; - acpi_semaphore temp_semaphore; - - ACPI_FUNCTION_ENTRY(); - - /* - * We are going to simply delete the existing semaphore and - * create a new one! - */ - status = - acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore); - if (ACPI_SUCCESS(status)) { - (void)acpi_os_delete_semaphore(obj_desc->event.os_semaphore); - obj_desc->event.os_semaphore = temp_semaphore; - } - - return (status); -} diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c deleted file mode 100644 index 0ecdb70c4980..000000000000 --- a/drivers/acpi/executer/exutils.c +++ /dev/null @@ -1,421 +0,0 @@ - -/****************************************************************************** - * - * Module Name: exutils - interpreter/scanner utilities - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -/* - * DEFINE_AML_GLOBALS is tested in amlcode.h - * to determine whether certain global names should be "defined" or only - * "declared" in the current compilation. This enhances maintainability - * by enabling a single header file to embody all knowledge of the names - * in question. - * - * Exactly one module of any executable should #define DEFINE_GLOBALS - * before #including the header files which use this convention. The - * names in question will be defined and initialized in that module, - * and declared as extern in all other modules which #include those - * header files. - */ - -#define DEFINE_AML_GLOBALS - -#include -#include -#include -#include - -#define _COMPONENT ACPI_EXECUTER -ACPI_MODULE_NAME("exutils") - -/* Local prototypes */ -static u32 acpi_ex_digits_needed(acpi_integer value, u32 base); - -#ifndef ACPI_NO_METHOD_EXECUTION -/******************************************************************************* - * - * FUNCTION: acpi_ex_enter_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Enter the interpreter execution region. Failure to enter - * the interpreter region is a fatal system error. Used in - * conjunction with exit_interpreter. - * - ******************************************************************************/ - -void acpi_ex_enter_interpreter(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ex_enter_interpreter); - - status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not acquire AML Interpreter mutex")); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_reacquire_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Reacquire the interpreter execution region from within the - * interpreter code. Failure to enter the interpreter region is a - * fatal system error. Used in conjuction with - * relinquish_interpreter - * - ******************************************************************************/ - -void acpi_ex_reacquire_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_reacquire_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter, - * since it was not actually released by acpi_ex_relinquish_interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_enter_interpreter(); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_exit_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Exit the interpreter execution region. This is the top level - * routine used to exit the interpreter when all processing has - * been completed. - * - ******************************************************************************/ - -void acpi_ex_exit_interpreter(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ex_exit_interpreter); - - status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not release AML Interpreter mutex")); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_relinquish_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Exit the interpreter execution region, from within the - * interpreter - before attempting an operation that will possibly - * block the running thread. - * - * Cases where the interpreter is unlocked internally - * 1) Method to be blocked on a Sleep() AML opcode - * 2) Method to be blocked on an Acquire() AML opcode - * 3) Method to be blocked on a Wait() AML opcode - * 4) Method to be blocked to acquire the global lock - * 5) Method to be blocked waiting to execute a serialized control method - * that is currently executing - * 6) About to invoke a user-installed opregion handler - * - ******************************************************************************/ - -void acpi_ex_relinquish_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_relinquish_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_exit_interpreter(); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_truncate_for32bit_table - * - * PARAMETERS: obj_desc - Object to be truncated - * - * RETURN: none - * - * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is - * 32-bit, as determined by the revision of the DSDT. - * - ******************************************************************************/ - -void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) -{ - - ACPI_FUNCTION_ENTRY(); - - /* - * Object must be a valid number and we must be executing - * a control method. NS node could be there for AML_INT_NAMEPATH_OP. - */ - if ((!obj_desc) || - (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) || - (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { - return; - } - - if (acpi_gbl_integer_byte_width == 4) { - /* - * We are running a method that exists in a 32-bit ACPI table. - * Truncate the value to 32 bits by zeroing out the upper 32-bit field - */ - obj_desc->integer.value &= (acpi_integer) ACPI_UINT32_MAX; - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_acquire_global_lock - * - * PARAMETERS: field_flags - Flags with Lock rule: - * always_lock or never_lock - * - * RETURN: None - * - * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field - * flags specifiy that it is to be obtained before field access. - * - ******************************************************************************/ - -void acpi_ex_acquire_global_lock(u32 field_flags) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ex_acquire_global_lock); - - /* Only use the lock if the always_lock bit is set */ - - if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { - return_VOID; - } - - /* Attempt to get the global lock, wait forever */ - - status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER, - acpi_gbl_global_lock_mutex, - acpi_os_get_thread_id()); - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not acquire Global Lock")); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_release_global_lock - * - * PARAMETERS: field_flags - Flags with Lock rule: - * always_lock or never_lock - * - * RETURN: None - * - * DESCRIPTION: Release the ACPI hardware Global Lock - * - ******************************************************************************/ - -void acpi_ex_release_global_lock(u32 field_flags) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ex_release_global_lock); - - /* Only use the lock if the always_lock bit is set */ - - if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { - return_VOID; - } - - /* Release the global lock */ - - status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); - if (ACPI_FAILURE(status)) { - - /* Report the error, but there isn't much else we can do */ - - ACPI_EXCEPTION((AE_INFO, status, - "Could not release Global Lock")); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_digits_needed - * - * PARAMETERS: Value - Value to be represented - * Base - Base of representation - * - * RETURN: The number of digits. - * - * DESCRIPTION: Calculate the number of digits needed to represent the Value - * in the given Base (Radix) - * - ******************************************************************************/ - -static u32 acpi_ex_digits_needed(acpi_integer value, u32 base) -{ - u32 num_digits; - acpi_integer current_value; - - ACPI_FUNCTION_TRACE(ex_digits_needed); - - /* acpi_integer is unsigned, so we don't worry about a '-' prefix */ - - if (value == 0) { - return_UINT32(1); - } - - current_value = value; - num_digits = 0; - - /* Count the digits in the requested base */ - - while (current_value) { - (void)acpi_ut_short_divide(current_value, base, ¤t_value, - NULL); - num_digits++; - } - - return_UINT32(num_digits); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_eisa_id_to_string - * - * PARAMETERS: numeric_id - EISA ID to be converted - * out_string - Where to put the converted string (8 bytes) - * - * RETURN: None - * - * DESCRIPTION: Convert a numeric EISA ID to string representation - * - ******************************************************************************/ - -void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string) -{ - u32 eisa_id; - - ACPI_FUNCTION_ENTRY(); - - /* Swap ID to big-endian to get contiguous bits */ - - eisa_id = acpi_ut_dword_byte_swap(numeric_id); - - out_string[0] = (char)('@' + (((unsigned long)eisa_id >> 26) & 0x1f)); - out_string[1] = (char)('@' + ((eisa_id >> 21) & 0x1f)); - out_string[2] = (char)('@' + ((eisa_id >> 16) & 0x1f)); - out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 12); - out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 8); - out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 4); - out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 0); - out_string[7] = 0; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_unsigned_integer_to_string - * - * PARAMETERS: Value - Value to be converted - * out_string - Where to put the converted string (8 bytes) - * - * RETURN: None, string - * - * DESCRIPTION: Convert a number to string representation. Assumes string - * buffer is large enough to hold the string. - * - ******************************************************************************/ - -void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string) -{ - u32 count; - u32 digits_needed; - u32 remainder; - - ACPI_FUNCTION_ENTRY(); - - digits_needed = acpi_ex_digits_needed(value, 10); - out_string[digits_needed] = 0; - - for (count = digits_needed; count > 0; count--) { - (void)acpi_ut_short_divide(value, 10, &value, &remainder); - out_string[count - 1] = (char)('0' + remainder); - } -} - -#endif diff --git a/drivers/acpi/hardware/Makefile b/drivers/acpi/hardware/Makefile deleted file mode 100644 index 238fbe513b82..000000000000 --- a/drivers/acpi/hardware/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -obj-y := hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o - -obj-$(ACPI_FUTURE_USAGE) += hwtimer.o - -EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c deleted file mode 100644 index c76e3cd7e749..000000000000 --- a/drivers/acpi/hardware/hwacpi.c +++ /dev/null @@ -1,185 +0,0 @@ - -/****************************************************************************** - * - * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include - -#define _COMPONENT ACPI_HARDWARE -ACPI_MODULE_NAME("hwacpi") - -/****************************************************************************** - * - * FUNCTION: acpi_hw_set_mode - * - * PARAMETERS: Mode - SYS_MODE_ACPI or SYS_MODE_LEGACY - * - * RETURN: Status - * - * DESCRIPTION: Transitions the system into the requested mode. - * - ******************************************************************************/ -acpi_status acpi_hw_set_mode(u32 mode) -{ - - acpi_status status; - u32 retry; - - ACPI_FUNCTION_TRACE(hw_set_mode); - - /* - * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, - * system does not support mode transition. - */ - if (!acpi_gbl_FADT.smi_command) { - ACPI_ERROR((AE_INFO, - "No SMI_CMD in FADT, mode transition failed")); - return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); - } - - /* - * ACPI 2.0 clarified the meaning of ACPI_ENABLE and ACPI_DISABLE - * in FADT: If it is zero, enabling or disabling is not supported. - * As old systems may have used zero for mode transition, - * we make sure both the numbers are zero to determine these - * transitions are not supported. - */ - if (!acpi_gbl_FADT.acpi_enable && !acpi_gbl_FADT.acpi_disable) { - ACPI_ERROR((AE_INFO, - "No ACPI mode transition supported in this system (enable/disable both zero)")); - return_ACPI_STATUS(AE_OK); - } - - switch (mode) { - case ACPI_SYS_MODE_ACPI: - - /* BIOS should have disabled ALL fixed and GP events */ - - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.acpi_enable, 8); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Attempting to enable ACPI mode\n")); - break; - - case ACPI_SYS_MODE_LEGACY: - - /* - * BIOS should clear all fixed status bits and restore fixed event - * enable bits to default - */ - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.acpi_disable, - 8); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Attempting to enable Legacy (non-ACPI) mode\n")); - break; - - default: - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not write ACPI mode change")); - return_ACPI_STATUS(status); - } - - /* - * Some hardware takes a LONG time to switch modes. Give them 3 sec to - * do so, but allow faster systems to proceed more quickly. - */ - retry = 3000; - while (retry) { - if (acpi_hw_get_mode() == mode) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Mode %X successfully enabled\n", - mode)); - return_ACPI_STATUS(AE_OK); - } - acpi_os_stall(1000); - retry--; - } - - ACPI_ERROR((AE_INFO, "Hardware did not change modes")); - return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_hw_get_mode - * - * PARAMETERS: none - * - * RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY - * - * DESCRIPTION: Return current operating state of system. Determined by - * querying the SCI_EN bit. - * - ******************************************************************************/ - -u32 acpi_hw_get_mode(void) -{ - acpi_status status; - u32 value; - - ACPI_FUNCTION_TRACE(hw_get_mode); - - /* - * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, - * system does not support mode transition. - */ - if (!acpi_gbl_FADT.smi_command) { - return_UINT32(ACPI_SYS_MODE_ACPI); - } - - status = acpi_get_register(ACPI_BITREG_SCI_ENABLE, &value); - if (ACPI_FAILURE(status)) { - return_UINT32(ACPI_SYS_MODE_LEGACY); - } - - if (value) { - return_UINT32(ACPI_SYS_MODE_ACPI); - } else { - return_UINT32(ACPI_SYS_MODE_LEGACY); - } -} diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c deleted file mode 100644 index 2b4a85a839d1..000000000000 --- a/drivers/acpi/hardware/hwgpe.c +++ /dev/null @@ -1,469 +0,0 @@ - -/****************************************************************************** - * - * Module Name: hwgpe - Low level GPE enable/disable/clear functions - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_HARDWARE -ACPI_MODULE_NAME("hwgpe") - -/* Local prototypes */ -static acpi_status -acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, - void *context); - -/****************************************************************************** - * - * FUNCTION: acpi_hw_low_disable_gpe - * - * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled - * - * RETURN: Status - * - * DESCRIPTION: Disable a single GPE in the enable register. - * - ******************************************************************************/ - -acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) -{ - struct acpi_gpe_register_info *gpe_register_info; - acpi_status status; - u32 enable_mask; - - /* Get the info block for the entire GPE register */ - - gpe_register_info = gpe_event_info->register_info; - if (!gpe_register_info) { - return (AE_NOT_EXIST); - } - - /* Get current value of the enable register that contains this GPE */ - - status = acpi_read(&enable_mask, &gpe_register_info->enable_address); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Clear just the bit that corresponds to this GPE */ - - ACPI_CLEAR_BIT(enable_mask, - ((u32) 1 << - (gpe_event_info->gpe_number - - gpe_register_info->base_gpe_number))); - - /* Write the updated enable mask */ - - status = acpi_write(enable_mask, &gpe_register_info->enable_address); - return (status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_write_gpe_enable_reg - * - * PARAMETERS: gpe_event_info - Info block for the GPE to be enabled - * - * RETURN: Status - * - * DESCRIPTION: Write a GPE enable register. Note: The bit for this GPE must - * already be cleared or set in the parent register - * enable_for_run mask. - * - ******************************************************************************/ - -acpi_status -acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info) -{ - struct acpi_gpe_register_info *gpe_register_info; - acpi_status status; - - ACPI_FUNCTION_ENTRY(); - - /* Get the info block for the entire GPE register */ - - gpe_register_info = gpe_event_info->register_info; - if (!gpe_register_info) { - return (AE_NOT_EXIST); - } - - /* Write the entire GPE (runtime) enable register */ - - status = acpi_write(gpe_register_info->enable_for_run, - &gpe_register_info->enable_address); - - return (status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_clear_gpe - * - * PARAMETERS: gpe_event_info - Info block for the GPE to be cleared - * - * RETURN: Status - * - * DESCRIPTION: Clear the status bit for a single GPE. - * - ******************************************************************************/ - -acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) -{ - acpi_status status; - u8 register_bit; - - ACPI_FUNCTION_ENTRY(); - - register_bit = (u8) - (1 << - (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number)); - - /* - * Write a one to the appropriate bit in the status register to - * clear this GPE. - */ - status = acpi_write(register_bit, - &gpe_event_info->register_info->status_address); - - return (status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_get_gpe_status - * - * PARAMETERS: gpe_event_info - Info block for the GPE to queried - * event_status - Where the GPE status is returned - * - * RETURN: Status - * - * DESCRIPTION: Return the status of a single GPE. - * - ******************************************************************************/ - -acpi_status -acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, - acpi_event_status * event_status) -{ - u32 in_byte; - u8 register_bit; - struct acpi_gpe_register_info *gpe_register_info; - acpi_status status; - acpi_event_status local_event_status = 0; - - ACPI_FUNCTION_ENTRY(); - - if (!event_status) { - return (AE_BAD_PARAMETER); - } - - /* Get the info block for the entire GPE register */ - - gpe_register_info = gpe_event_info->register_info; - - /* Get the register bitmask for this GPE */ - - register_bit = (u8) - (1 << - (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number)); - - /* GPE currently enabled? (enabled for runtime?) */ - - if (register_bit & gpe_register_info->enable_for_run) { - local_event_status |= ACPI_EVENT_FLAG_ENABLED; - } - - /* GPE enabled for wake? */ - - if (register_bit & gpe_register_info->enable_for_wake) { - local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED; - } - - /* GPE currently active (status bit == 1)? */ - - status = acpi_read(&in_byte, &gpe_register_info->status_address); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - if (register_bit & in_byte) { - local_event_status |= ACPI_EVENT_FLAG_SET; - } - - /* Set return value */ - - (*event_status) = local_event_status; - - unlock_and_exit: - return (status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_disable_gpe_block - * - * PARAMETERS: gpe_xrupt_info - GPE Interrupt info - * gpe_block - Gpe Block info - * - * RETURN: Status - * - * DESCRIPTION: Disable all GPEs within a single GPE block - * - ******************************************************************************/ - -acpi_status -acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, void *context) -{ - u32 i; - acpi_status status; - - /* Examine each GPE Register within the block */ - - for (i = 0; i < gpe_block->register_count; i++) { - - /* Disable all GPEs in this register */ - - status = - acpi_write(0x00, - &gpe_block->register_info[i].enable_address); - if (ACPI_FAILURE(status)) { - return (status); - } - } - - return (AE_OK); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_clear_gpe_block - * - * PARAMETERS: gpe_xrupt_info - GPE Interrupt info - * gpe_block - Gpe Block info - * - * RETURN: Status - * - * DESCRIPTION: Clear status bits for all GPEs within a single GPE block - * - ******************************************************************************/ - -acpi_status -acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, void *context) -{ - u32 i; - acpi_status status; - - /* Examine each GPE Register within the block */ - - for (i = 0; i < gpe_block->register_count; i++) { - - /* Clear status on all GPEs in this register */ - - status = - acpi_write(0xFF, - &gpe_block->register_info[i].status_address); - if (ACPI_FAILURE(status)) { - return (status); - } - } - - return (AE_OK); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_enable_runtime_gpe_block - * - * PARAMETERS: gpe_xrupt_info - GPE Interrupt info - * gpe_block - Gpe Block info - * - * RETURN: Status - * - * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes - * combination wake/run GPEs. - * - ******************************************************************************/ - -acpi_status -acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, void *context) -{ - u32 i; - acpi_status status; - - /* NOTE: assumes that all GPEs are currently disabled */ - - /* Examine each GPE Register within the block */ - - for (i = 0; i < gpe_block->register_count; i++) { - if (!gpe_block->register_info[i].enable_for_run) { - continue; - } - - /* Enable all "runtime" GPEs in this register */ - - status = acpi_write(gpe_block->register_info[i].enable_for_run, - &gpe_block->register_info[i]. - enable_address); - if (ACPI_FAILURE(status)) { - return (status); - } - } - - return (AE_OK); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_enable_wakeup_gpe_block - * - * PARAMETERS: gpe_xrupt_info - GPE Interrupt info - * gpe_block - Gpe Block info - * - * RETURN: Status - * - * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes - * combination wake/run GPEs. - * - ******************************************************************************/ - -static acpi_status -acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, - void *context) -{ - u32 i; - acpi_status status; - - /* Examine each GPE Register within the block */ - - for (i = 0; i < gpe_block->register_count; i++) { - if (!gpe_block->register_info[i].enable_for_wake) { - continue; - } - - /* Enable all "wake" GPEs in this register */ - - status = acpi_write(gpe_block->register_info[i].enable_for_wake, - &gpe_block->register_info[i]. - enable_address); - if (ACPI_FAILURE(status)) { - return (status); - } - } - - return (AE_OK); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_disable_all_gpes - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Disable and clear all GPEs in all GPE blocks - * - ******************************************************************************/ - -acpi_status acpi_hw_disable_all_gpes(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(hw_disable_all_gpes); - - status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); - status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL); - return_ACPI_STATUS(status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_enable_all_runtime_gpes - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks - * - ******************************************************************************/ - -acpi_status acpi_hw_enable_all_runtime_gpes(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes); - - status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL); - return_ACPI_STATUS(status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_enable_all_wakeup_gpes - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks - * - ******************************************************************************/ - -acpi_status acpi_hw_enable_all_wakeup_gpes(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes); - - status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL); - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c deleted file mode 100644 index 4bc3bbba6e9c..000000000000 --- a/drivers/acpi/hardware/hwregs.c +++ /dev/null @@ -1,353 +0,0 @@ - -/******************************************************************************* - * - * Module Name: hwregs - Read/write access functions for the various ACPI - * control and status registers. - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_HARDWARE -ACPI_MODULE_NAME("hwregs") - -/******************************************************************************* - * - * FUNCTION: acpi_hw_clear_acpi_status - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Clears all fixed and general purpose status bits - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED - * - ******************************************************************************/ -acpi_status acpi_hw_clear_acpi_status(void) -{ - acpi_status status; - acpi_cpu_flags lock_flags = 0; - - ACPI_FUNCTION_TRACE(hw_clear_acpi_status); - - ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n", - ACPI_BITMASK_ALL_FIXED_STATUS, - (u16) acpi_gbl_FADT.xpm1a_event_block.address)); - - lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); - - status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, - ACPI_BITMASK_ALL_FIXED_STATUS); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - /* Clear the fixed events */ - - if (acpi_gbl_FADT.xpm1b_event_block.address) { - status = acpi_write(ACPI_BITMASK_ALL_FIXED_STATUS, - &acpi_gbl_FADT.xpm1b_event_block); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - } - - /* Clear the GPE Bits in all GPE registers in all GPE blocks */ - - status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL); - - unlock_and_exit: - acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_hw_get_register_bit_mask - * - * PARAMETERS: register_id - Index of ACPI Register to access - * - * RETURN: The bitmask to be used when accessing the register - * - * DESCRIPTION: Map register_id into a register bitmask. - * - ******************************************************************************/ - -struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) -{ - ACPI_FUNCTION_ENTRY(); - - if (register_id > ACPI_BITREG_MAX) { - ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X", - register_id)); - return (NULL); - } - - return (&acpi_gbl_bit_register_info[register_id]); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_register_read - * - * PARAMETERS: register_id - ACPI Register ID - * return_value - Where the register value is returned - * - * RETURN: Status and the value read. - * - * DESCRIPTION: Read from the specified ACPI register - * - ******************************************************************************/ -acpi_status -acpi_hw_register_read(u32 register_id, u32 * return_value) -{ - u32 value1 = 0; - u32 value2 = 0; - acpi_status status; - - ACPI_FUNCTION_TRACE(hw_register_read); - - switch (register_id) { - case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - - status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_event_block); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ - - status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_event_block); - value1 |= value2; - break; - - case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ - - status = acpi_read(&value1, &acpi_gbl_xpm1a_enable); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ - - status = acpi_read(&value2, &acpi_gbl_xpm1b_enable); - value1 |= value2; - break; - - case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ - - status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_control_block); - if (ACPI_FAILURE(status)) { - goto exit; - } - - status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_control_block); - value1 |= value2; - break; - - case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - - status = acpi_read(&value1, &acpi_gbl_FADT.xpm2_control_block); - break; - - case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - - status = acpi_read(&value1, &acpi_gbl_FADT.xpm_timer_block); - break; - - case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ - - status = - acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8); - break; - - default: - ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id)); - status = AE_BAD_PARAMETER; - break; - } - - exit: - - if (ACPI_SUCCESS(status)) { - *return_value = value1; - } - - return_ACPI_STATUS(status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_register_write - * - * PARAMETERS: register_id - ACPI Register ID - * Value - The value to write - * - * RETURN: Status - * - * DESCRIPTION: Write to the specified ACPI register - * - * NOTE: In accordance with the ACPI specification, this function automatically - * preserves the value of the following bits, meaning that these bits cannot be - * changed via this interface: - * - * PM1_CONTROL[0] = SCI_EN - * PM1_CONTROL[9] - * PM1_STATUS[11] - * - * ACPI References: - * 1) Hardware Ignored Bits: When software writes to a register with ignored - * bit fields, it preserves the ignored bit fields - * 2) SCI_EN: OSPM always preserves this bit position - * - ******************************************************************************/ - -acpi_status acpi_hw_register_write(u32 register_id, u32 value) -{ - acpi_status status; - u32 read_value; - - ACPI_FUNCTION_TRACE(hw_register_write); - - switch (register_id) { - case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - - /* Perform a read first to preserve certain bits (per ACPI spec) */ - - status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, - &read_value); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* Insert the bits to be preserved */ - - ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS, - read_value); - - /* Now we can write the data */ - - status = acpi_write(value, &acpi_gbl_FADT.xpm1a_event_block); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ - - status = acpi_write(value, &acpi_gbl_FADT.xpm1b_event_block); - break; - - case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ - - status = acpi_write(value, &acpi_gbl_xpm1a_enable); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ - - status = acpi_write(value, &acpi_gbl_xpm1b_enable); - break; - - case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ - - /* - * Perform a read first to preserve certain bits (per ACPI spec) - */ - status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, - &read_value); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* Insert the bits to be preserved */ - - ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS, - read_value); - - /* Now we can write the data */ - - status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block); - if (ACPI_FAILURE(status)) { - goto exit; - } - - status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block); - break; - - case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ - - status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block); - break; - - case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ - - status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block); - break; - - case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - - status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block); - break; - - case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - - status = acpi_write(value, &acpi_gbl_FADT.xpm_timer_block); - break; - - case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ - - /* SMI_CMD is currently always in IO space */ - - status = - acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8); - break; - - default: - status = AE_BAD_PARAMETER; - break; - } - - exit: - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c deleted file mode 100644 index 54dd3ee0760c..000000000000 --- a/drivers/acpi/hardware/hwsleep.c +++ /dev/null @@ -1,629 +0,0 @@ - -/****************************************************************************** - * - * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_HARDWARE -ACPI_MODULE_NAME("hwsleep") - -/******************************************************************************* - * - * FUNCTION: acpi_set_firmware_waking_vector - * - * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode - * entry point. - * - * RETURN: Status - * - * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS - * - ******************************************************************************/ -acpi_status -acpi_set_firmware_waking_vector(u32 physical_address) -{ - ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); - - - /* - * According to the ACPI specification 2.0c and later, the 64-bit - * waking vector should be cleared and the 32-bit waking vector should - * be used, unless we want the wake-up code to be called by the BIOS in - * Protected Mode. Some systems (for example HP dv5-1004nr) are known - * to fail to resume if the 64-bit vector is used. - */ - - /* Set the 32-bit vector */ - - acpi_gbl_FACS->firmware_waking_vector = physical_address; - - /* Clear the 64-bit vector if it exists */ - - if ((acpi_gbl_FACS->length > 32) && (acpi_gbl_FACS->version >= 1)) { - acpi_gbl_FACS->xfirmware_waking_vector = 0; - } - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) - -/******************************************************************************* - * - * FUNCTION: acpi_set_firmware_waking_vector64 - * - * PARAMETERS: physical_address - 64-bit physical address of ACPI protected - * mode entry point. - * - * RETURN: Status - * - * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if - * it exists in the table. - * - ******************************************************************************/ -acpi_status -acpi_set_firmware_waking_vector64(u64 physical_address) -{ - ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64); - - - /* Determine if the 64-bit vector actually exists */ - - if ((acpi_gbl_FACS->length <= 32) || (acpi_gbl_FACS->version < 1)) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* Clear 32-bit vector, set the 64-bit X_ vector */ - - acpi_gbl_FACS->firmware_waking_vector = 0; - acpi_gbl_FACS->xfirmware_waking_vector = physical_address; - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) - -/******************************************************************************* - * - * FUNCTION: acpi_enter_sleep_state_prep - * - * PARAMETERS: sleep_state - Which sleep state to enter - * - * RETURN: Status - * - * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231) - * This function must execute with interrupts enabled. - * We break sleeping into 2 stages so that OSPM can handle - * various OS-specific tasks between the two steps. - * - ******************************************************************************/ -acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) -{ - acpi_status status; - struct acpi_object_list arg_list; - union acpi_object arg; - - ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); - - /* - * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. - */ - status = acpi_get_sleep_type_data(sleep_state, - &acpi_gbl_sleep_type_a, - &acpi_gbl_sleep_type_b); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Setup parameter object */ - - arg_list.count = 1; - arg_list.pointer = &arg; - - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = sleep_state; - - /* Run the _PTS method */ - - status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - return_ACPI_STATUS(status); - } - - /* Setup the argument to _SST */ - - switch (sleep_state) { - case ACPI_STATE_S0: - arg.integer.value = ACPI_SST_WORKING; - break; - - case ACPI_STATE_S1: - case ACPI_STATE_S2: - case ACPI_STATE_S3: - arg.integer.value = ACPI_SST_SLEEPING; - break; - - case ACPI_STATE_S4: - arg.integer.value = ACPI_SST_SLEEP_CONTEXT; - break; - - default: - arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is off */ - break; - } - - /* - * Set the system indicators to show the desired sleep state. - * _SST is an optional method (return no error if not found) - */ - status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, - "While executing method _SST")); - } - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) - -/******************************************************************************* - * - * FUNCTION: acpi_enter_sleep_state - * - * PARAMETERS: sleep_state - Which sleep state to enter - * - * RETURN: Status - * - * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED - * - ******************************************************************************/ -acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) -{ - u32 PM1Acontrol; - u32 PM1Bcontrol; - struct acpi_bit_register_info *sleep_type_reg_info; - struct acpi_bit_register_info *sleep_enable_reg_info; - u32 in_value; - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); - - if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || - (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { - ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X", - acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); - return_ACPI_STATUS(AE_AML_OPERAND_VALUE); - } - - sleep_type_reg_info = - acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); - sleep_enable_reg_info = - acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); - - /* Clear wake status */ - - status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Clear all fixed and general purpose status bits */ - - status = acpi_hw_clear_acpi_status(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * 1) Disable/Clear all GPEs - * 2) Enable all wakeup GPEs - */ - status = acpi_hw_disable_all_gpes(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - acpi_gbl_system_awake_and_running = FALSE; - - status = acpi_hw_enable_all_wakeup_gpes(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Execute the _GTS method */ - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = sleep_state; - - status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - return_ACPI_STATUS(status); - } - - /* Get current value of PM1A control */ - - status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "Entering sleep state [S%d]\n", sleep_state)); - - /* Clear SLP_EN and SLP_TYP fields */ - - PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | - sleep_enable_reg_info->access_bit_mask); - PM1Bcontrol = PM1Acontrol; - - /* Insert SLP_TYP bits */ - - PM1Acontrol |= - (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); - PM1Bcontrol |= - (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); - - /* - * We split the writes of SLP_TYP and SLP_EN to workaround - * poorly implemented hardware. - */ - - /* Write #1: fill in SLP_TYP data */ - - status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, - PM1Acontrol); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, - PM1Bcontrol); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Insert SLP_ENABLE bit */ - - PM1Acontrol |= sleep_enable_reg_info->access_bit_mask; - PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask; - - /* Write #2: SLP_TYP + SLP_EN */ - - ACPI_FLUSH_CPU_CACHE(); - - status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, - PM1Acontrol); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, - PM1Bcontrol); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (sleep_state > ACPI_STATE_S3) { - /* - * We wanted to sleep > S3, but it didn't happen (by virtue of the - * fact that we are still executing!) - * - * Wait ten seconds, then try again. This is to get S4/S5 to work on - * all machines. - * - * We wait so long to allow chipsets that poll this reg very slowly to - * still read the right value. Ideally, this block would go - * away entirely. - */ - acpi_os_stall(10000000); - - status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, - sleep_enable_reg_info-> - access_bit_mask); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* Wait until we enter sleep state */ - - do { - status = acpi_get_register_unlocked(ACPI_BITREG_WAKE_STATUS, - &in_value); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Spin until we wake */ - - } while (!in_value); - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) - -/******************************************************************************* - * - * FUNCTION: acpi_enter_sleep_state_s4bios - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Perform a S4 bios request. - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED - * - ******************************************************************************/ -acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) -{ - u32 in_value; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); - - status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_hw_clear_acpi_status(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * 1) Disable/Clear all GPEs - * 2) Enable all wakeup GPEs - */ - status = acpi_hw_disable_all_gpes(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - acpi_gbl_system_awake_and_running = FALSE; - - status = acpi_hw_enable_all_wakeup_gpes(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - ACPI_FLUSH_CPU_CACHE(); - - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.S4bios_request, 8); - - do { - acpi_os_stall(1000); - status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } while (!in_value); - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) - -/******************************************************************************* - * - * FUNCTION: acpi_leave_sleep_state_prep - * - * PARAMETERS: sleep_state - Which sleep state we are exiting - * - * RETURN: Status - * - * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a - * sleep. - * Called with interrupts DISABLED. - * - ******************************************************************************/ -acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) -{ - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status; - struct acpi_bit_register_info *sleep_type_reg_info; - struct acpi_bit_register_info *sleep_enable_reg_info; - u32 PM1Acontrol; - u32 PM1Bcontrol; - - ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); - - /* - * Set SLP_TYPE and SLP_EN to state S0. - * This is unclear from the ACPI Spec, but it is required - * by some machines. - */ - status = acpi_get_sleep_type_data(ACPI_STATE_S0, - &acpi_gbl_sleep_type_a, - &acpi_gbl_sleep_type_b); - if (ACPI_SUCCESS(status)) { - sleep_type_reg_info = - acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); - sleep_enable_reg_info = - acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); - - /* Get current value of PM1A control */ - - status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, - &PM1Acontrol); - if (ACPI_SUCCESS(status)) { - - /* Clear SLP_EN and SLP_TYP fields */ - - PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | - sleep_enable_reg_info-> - access_bit_mask); - PM1Bcontrol = PM1Acontrol; - - /* Insert SLP_TYP bits */ - - PM1Acontrol |= - (acpi_gbl_sleep_type_a << sleep_type_reg_info-> - bit_position); - PM1Bcontrol |= - (acpi_gbl_sleep_type_b << sleep_type_reg_info-> - bit_position); - - /* Just ignore any errors */ - - (void)acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, - PM1Acontrol); - (void)acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, - PM1Bcontrol); - } - } - - /* Execute the _BFS method */ - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = sleep_state; - - status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_leave_sleep_state - * - * PARAMETERS: sleep_state - Which sleep state we just exited - * - * RETURN: Status - * - * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep - * Called with interrupts ENABLED. - * - ******************************************************************************/ -acpi_status acpi_leave_sleep_state(u8 sleep_state) -{ - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); - - /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ - - acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; - - /* Setup parameter object */ - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - - /* Ignore any errors from these methods */ - - arg.integer.value = ACPI_SST_WAKING; - status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); - } - - /* - * GPEs must be enabled before _WAK is called as GPEs - * might get fired there - * - * Restore the GPEs: - * 1) Disable/Clear all GPEs - * 2) Enable all runtime GPEs - */ - status = acpi_hw_disable_all_gpes(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - status = acpi_hw_enable_all_runtime_gpes(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - arg.integer.value = sleep_state; - status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); - } - /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ - - /* - * Some BIOSes assume that WAK_STS will be cleared on resume and use - * it to determine whether the system is rebooting or resuming. Clear - * it for compatibility. - */ - acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); - - acpi_gbl_system_awake_and_running = TRUE; - - /* Enable power button */ - - (void) - acpi_set_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1); - - (void) - acpi_set_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON].status_register_id, 1); - - arg.integer.value = ACPI_SST_WORKING; - status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); - } - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state) diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c deleted file mode 100644 index d1eac2aad728..000000000000 --- a/drivers/acpi/hardware/hwtimer.c +++ /dev/null @@ -1,188 +0,0 @@ - -/****************************************************************************** - * - * Name: hwtimer.c - ACPI Power Management Timer Interface - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include - -#define _COMPONENT ACPI_HARDWARE -ACPI_MODULE_NAME("hwtimer") - -/****************************************************************************** - * - * FUNCTION: acpi_get_timer_resolution - * - * PARAMETERS: Resolution - Where the resolution is returned - * - * RETURN: Status and timer resolution - * - * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits). - * - ******************************************************************************/ -acpi_status acpi_get_timer_resolution(u32 * resolution) -{ - ACPI_FUNCTION_TRACE(acpi_get_timer_resolution); - - if (!resolution) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) { - *resolution = 24; - } else { - *resolution = 32; - } - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution) - -/****************************************************************************** - * - * FUNCTION: acpi_get_timer - * - * PARAMETERS: Ticks - Where the timer value is returned - * - * RETURN: Status and current timer value (ticks) - * - * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks). - * - ******************************************************************************/ -acpi_status acpi_get_timer(u32 * ticks) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_get_timer); - - if (!ticks) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - status = - acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT.xpm_timer_block); - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_timer) - -/****************************************************************************** - * - * FUNCTION: acpi_get_timer_duration - * - * PARAMETERS: start_ticks - Starting timestamp - * end_ticks - End timestamp - * time_elapsed - Where the elapsed time is returned - * - * RETURN: Status and time_elapsed - * - * DESCRIPTION: Computes the time elapsed (in microseconds) between two - * PM Timer time stamps, taking into account the possibility of - * rollovers, the timer resolution, and timer frequency. - * - * The PM Timer's clock ticks at roughly 3.6 times per - * _microsecond_, and its clock continues through Cx state - * transitions (unlike many CPU timestamp counters) -- making it - * a versatile and accurate timer. - * - * Note that this function accommodates only a single timer - * rollover. Thus for 24-bit timers, this function should only - * be used for calculating durations less than ~4.6 seconds - * (~20 minutes for 32-bit timers) -- calculations below: - * - * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec - * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes - * - ******************************************************************************/ -acpi_status -acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) -{ - acpi_status status; - u32 delta_ticks; - acpi_integer quotient; - - ACPI_FUNCTION_TRACE(acpi_get_timer_duration); - - if (!time_elapsed) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* - * Compute Tick Delta: - * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. - */ - if (start_ticks < end_ticks) { - delta_ticks = end_ticks - start_ticks; - } else if (start_ticks > end_ticks) { - if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) { - - /* 24-bit Timer */ - - delta_ticks = - (((0x00FFFFFF - start_ticks) + - end_ticks) & 0x00FFFFFF); - } else { - /* 32-bit Timer */ - - delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks; - } - } else { /* start_ticks == end_ticks */ - - *time_elapsed = 0; - return_ACPI_STATUS(AE_OK); - } - - /* - * Compute Duration (Requires a 64-bit multiply and divide): - * - * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY; - */ - status = acpi_ut_short_divide(((u64) delta_ticks) * 1000000, - PM_TIMER_FREQUENCY, "ient, NULL); - - *time_elapsed = (u32) quotient; - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_timer_duration) diff --git a/drivers/acpi/hardware/hwxface.c b/drivers/acpi/hardware/hwxface.c deleted file mode 100644 index a4456fc9462d..000000000000 --- a/drivers/acpi/hardware/hwxface.c +++ /dev/null @@ -1,593 +0,0 @@ - -/****************************************************************************** - * - * Module Name: hwxface - Public ACPICA hardware interfaces - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_HARDWARE -ACPI_MODULE_NAME("hwxface") - -/****************************************************************************** - * - * FUNCTION: acpi_reset - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Set reset register in memory or IO space. Note: Does not - * support reset register in PCI config space, this must be - * handled separately. - * - ******************************************************************************/ -acpi_status acpi_reset(void) -{ - struct acpi_generic_address *reset_reg; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_reset); - - reset_reg = &acpi_gbl_FADT.reset_register; - - /* Check if the reset register is supported */ - - if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || - !reset_reg->address) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* Write the reset value to the reset register */ - - status = acpi_write(acpi_gbl_FADT.reset_value, reset_reg); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_reset) - -/****************************************************************************** - * - * FUNCTION: acpi_read - * - * PARAMETERS: Value - Where the value is returned - * Reg - GAS register structure - * - * RETURN: Status - * - * DESCRIPTION: Read from either memory or IO space. - * - ******************************************************************************/ -acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) -{ - u32 width; - u64 address; - acpi_status status; - - ACPI_FUNCTION_NAME(acpi_read); - - /* - * Must have a valid pointer to a GAS structure, and - * a non-zero address within. However, don't return an error - * because the PM1A/B code must not fail if B isn't present. - */ - if (!reg) { - return (AE_OK); - } - - /* Get a local copy of the address. Handles possible alignment issues */ - - ACPI_MOVE_64_TO_64(&address, ®->address); - if (!address) { - return (AE_OK); - } - - /* Supported widths are 8/16/32 */ - - width = reg->bit_width; - if ((width != 8) && (width != 16) && (width != 32)) { - return (AE_SUPPORT); - } - - /* Initialize entire 32-bit return value to zero */ - - *value = 0; - - /* - * Two address spaces supported: Memory or IO. - * PCI_Config is not supported here because the GAS struct is insufficient - */ - switch (reg->space_id) { - case ACPI_ADR_SPACE_SYSTEM_MEMORY: - - status = acpi_os_read_memory((acpi_physical_address) address, - value, width); - break; - - case ACPI_ADR_SPACE_SYSTEM_IO: - - status = - acpi_os_read_port((acpi_io_address) address, value, width); - break; - - default: - ACPI_ERROR((AE_INFO, - "Unsupported address space: %X", reg->space_id)); - return (AE_BAD_PARAMETER); - } - - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", - *value, width, ACPI_FORMAT_UINT64(address), - acpi_ut_get_region_name(reg->space_id))); - - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_read) - -/****************************************************************************** - * - * FUNCTION: acpi_write - * - * PARAMETERS: Value - To be written - * Reg - GAS register structure - * - * RETURN: Status - * - * DESCRIPTION: Write to either memory or IO space. - * - ******************************************************************************/ -acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) -{ - u32 width; - u64 address; - acpi_status status; - - ACPI_FUNCTION_NAME(acpi_write); - - /* - * Must have a valid pointer to a GAS structure, and - * a non-zero address within. However, don't return an error - * because the PM1A/B code must not fail if B isn't present. - */ - if (!reg) { - return (AE_OK); - } - - /* Get a local copy of the address. Handles possible alignment issues */ - - ACPI_MOVE_64_TO_64(&address, ®->address); - if (!address) { - return (AE_OK); - } - - /* Supported widths are 8/16/32 */ - - width = reg->bit_width; - if ((width != 8) && (width != 16) && (width != 32)) { - return (AE_SUPPORT); - } - - /* - * Two address spaces supported: Memory or IO. - * PCI_Config is not supported here because the GAS struct is insufficient - */ - switch (reg->space_id) { - case ACPI_ADR_SPACE_SYSTEM_MEMORY: - - status = acpi_os_write_memory((acpi_physical_address) address, - value, width); - break; - - case ACPI_ADR_SPACE_SYSTEM_IO: - - status = acpi_os_write_port((acpi_io_address) address, value, - width); - break; - - default: - ACPI_ERROR((AE_INFO, - "Unsupported address space: %X", reg->space_id)); - return (AE_BAD_PARAMETER); - } - - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", - value, width, ACPI_FORMAT_UINT64(address), - acpi_ut_get_region_name(reg->space_id))); - - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_write) - -/******************************************************************************* - * - * FUNCTION: acpi_get_register_unlocked - * - * PARAMETERS: register_id - ID of ACPI bit_register to access - * return_value - Value that was read from the register - * - * RETURN: Status and the value read from specified Register. Value - * returned is normalized to bit0 (is shifted all the way right) - * - * DESCRIPTION: ACPI bit_register read function. Does not acquire the HW lock. - * - ******************************************************************************/ -acpi_status acpi_get_register_unlocked(u32 register_id, u32 *return_value) -{ - u32 register_value = 0; - struct acpi_bit_register_info *bit_reg_info; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_get_register_unlocked); - - /* Get the info structure corresponding to the requested ACPI Register */ - - bit_reg_info = acpi_hw_get_bit_register_info(register_id); - if (!bit_reg_info) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Read from the register */ - - status = acpi_hw_register_read(bit_reg_info->parent_register, - ®ister_value); - - if (ACPI_SUCCESS(status)) { - - /* Normalize the value that was read */ - - register_value = - ((register_value & bit_reg_info->access_bit_mask) - >> bit_reg_info->bit_position); - - *return_value = register_value; - - ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read value %8.8X register %X\n", - register_value, - bit_reg_info->parent_register)); - } - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_register_unlocked) - -/******************************************************************************* - * - * FUNCTION: acpi_get_register - * - * PARAMETERS: register_id - ID of ACPI bit_register to access - * return_value - Value that was read from the register - * - * RETURN: Status and the value read from specified Register. Value - * returned is normalized to bit0 (is shifted all the way right) - * - * DESCRIPTION: ACPI bit_register read function. - * - ******************************************************************************/ -acpi_status acpi_get_register(u32 register_id, u32 *return_value) -{ - acpi_status status; - acpi_cpu_flags flags; - - flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); - status = acpi_get_register_unlocked(register_id, return_value); - acpi_os_release_lock(acpi_gbl_hardware_lock, flags); - - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_register) - -/******************************************************************************* - * - * FUNCTION: acpi_set_register - * - * PARAMETERS: register_id - ID of ACPI bit_register to access - * Value - (only used on write) value to write to the - * Register, NOT pre-normalized to the bit pos - * - * RETURN: Status - * - * DESCRIPTION: ACPI Bit Register write function. - * - ******************************************************************************/ -acpi_status acpi_set_register(u32 register_id, u32 value) -{ - u32 register_value = 0; - struct acpi_bit_register_info *bit_reg_info; - acpi_status status; - acpi_cpu_flags lock_flags; - - ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id); - - /* Get the info structure corresponding to the requested ACPI Register */ - - bit_reg_info = acpi_hw_get_bit_register_info(register_id); - if (!bit_reg_info) { - ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X", - register_id)); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); - - /* Always do a register read first so we can insert the new bits */ - - status = acpi_hw_register_read(bit_reg_info->parent_register, - ®ister_value); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - /* - * Decode the Register ID - * Register ID = [Register block ID] | [bit ID] - * - * Check bit ID to fine locate Register offset. - * Check Mask to determine Register offset, and then read-write. - */ - switch (bit_reg_info->parent_register) { - case ACPI_REGISTER_PM1_STATUS: - - /* - * Status Registers are different from the rest. Clear by - * writing 1, and writing 0 has no effect. So, the only relevant - * information is the single bit we're interested in, all others should - * be written as 0 so they will be left unchanged. - */ - value = ACPI_REGISTER_PREPARE_BITS(value, - bit_reg_info->bit_position, - bit_reg_info-> - access_bit_mask); - if (value) { - status = - acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, - (u16) value); - register_value = 0; - } - break; - - case ACPI_REGISTER_PM1_ENABLE: - - ACPI_REGISTER_INSERT_VALUE(register_value, - bit_reg_info->bit_position, - bit_reg_info->access_bit_mask, - value); - - status = acpi_hw_register_write(ACPI_REGISTER_PM1_ENABLE, - (u16) register_value); - break; - - case ACPI_REGISTER_PM1_CONTROL: - - /* - * Write the PM1 Control register. - * Note that at this level, the fact that there are actually TWO - * registers (A and B - and B may not exist) is abstracted. - */ - ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM1 control: Read %X\n", - register_value)); - - ACPI_REGISTER_INSERT_VALUE(register_value, - bit_reg_info->bit_position, - bit_reg_info->access_bit_mask, - value); - - status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, - (u16) register_value); - break; - - case ACPI_REGISTER_PM2_CONTROL: - - status = acpi_hw_register_read(ACPI_REGISTER_PM2_CONTROL, - ®ister_value); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "PM2 control: Read %X from %8.8X%8.8X\n", - register_value, - ACPI_FORMAT_UINT64(acpi_gbl_FADT. - xpm2_control_block. - address))); - - ACPI_REGISTER_INSERT_VALUE(register_value, - bit_reg_info->bit_position, - bit_reg_info->access_bit_mask, - value); - - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "About to write %4.4X to %8.8X%8.8X\n", - register_value, - ACPI_FORMAT_UINT64(acpi_gbl_FADT. - xpm2_control_block. - address))); - - status = acpi_hw_register_write(ACPI_REGISTER_PM2_CONTROL, - (u8) (register_value)); - break; - - default: - break; - } - - unlock_and_exit: - - acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); - - /* Normalize the value that was read */ - - ACPI_DEBUG_EXEC(register_value = - ((register_value & bit_reg_info->access_bit_mask) >> - bit_reg_info->bit_position)); - - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Set bits: %8.8X actual %8.8X register %X\n", value, - register_value, bit_reg_info->parent_register)); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_set_register) - -/******************************************************************************* - * - * FUNCTION: acpi_get_sleep_type_data - * - * PARAMETERS: sleep_state - Numeric sleep state - * *sleep_type_a - Where SLP_TYPa is returned - * *sleep_type_b - Where SLP_TYPb is returned - * - * RETURN: Status - ACPI status - * - * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep - * state. - * - ******************************************************************************/ -acpi_status -acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) -{ - acpi_status status = AE_OK; - struct acpi_evaluate_info *info; - - ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data); - - /* Validate parameters */ - - if ((sleep_state > ACPI_S_STATES_MAX) || !sleep_type_a || !sleep_type_b) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Allocate the evaluation information block */ - - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); - if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - info->pathname = - ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]); - - /* Evaluate the namespace object containing the values for this state */ - - status = acpi_ns_evaluate(info); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "%s while evaluating SleepState [%s]\n", - acpi_format_exception(status), - info->pathname)); - - goto cleanup; - } - - /* Must have a return object */ - - if (!info->return_object) { - ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]", - info->pathname)); - status = AE_NOT_EXIST; - } - - /* It must be of type Package */ - - else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) { - ACPI_ERROR((AE_INFO, - "Sleep State return object is not a Package")); - status = AE_AML_OPERAND_TYPE; - } - - /* - * The package must have at least two elements. NOTE (March 2005): This - * goes against the current ACPI spec which defines this object as a - * package with one encoded DWORD element. However, existing practice - * by BIOS vendors seems to be to have 2 or more elements, at least - * one per sleep type (A/B). - */ - else if (info->return_object->package.count < 2) { - ACPI_ERROR((AE_INFO, - "Sleep State return package does not have at least two elements")); - status = AE_AML_NO_OPERAND; - } - - /* The first two elements must both be of type Integer */ - - else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0]) - != ACPI_TYPE_INTEGER) || - (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1]) - != ACPI_TYPE_INTEGER)) { - ACPI_ERROR((AE_INFO, - "Sleep State return package elements are not both Integers (%s, %s)", - acpi_ut_get_object_type_name(info->return_object-> - package.elements[0]), - acpi_ut_get_object_type_name(info->return_object-> - package.elements[1]))); - status = AE_AML_OPERAND_TYPE; - } else { - /* Valid _Sx_ package size, type, and value */ - - *sleep_type_a = (u8) - (info->return_object->package.elements[0])->integer.value; - *sleep_type_b = (u8) - (info->return_object->package.elements[1])->integer.value; - } - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "While evaluating SleepState [%s], bad Sleep object %p type %s", - info->pathname, info->return_object, - acpi_ut_get_object_type_name(info-> - return_object))); - } - - acpi_ut_remove_reference(info->return_object); - - cleanup: - ACPI_FREE(info); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data) diff --git a/drivers/acpi/main.c b/drivers/acpi/main.c new file mode 100644 index 000000000000..d8242772de92 --- /dev/null +++ b/drivers/acpi/main.c @@ -0,0 +1,696 @@ +/* + * sleep.c - ACPI sleep support. + * + * Copyright (c) 2005 Alexey Starikovskiy + * Copyright (c) 2004 David Shaohua Li + * Copyright (c) 2000-2003 Patrick Mochel + * Copyright (c) 2003 Open Source Development Lab + * + * This file is released under the GPLv2. + * + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include "sleep.h" + +u8 sleep_states[ACPI_S_STATE_COUNT]; + +static void acpi_sleep_tts_switch(u32 acpi_state) +{ + union acpi_object in_arg = { ACPI_TYPE_INTEGER }; + struct acpi_object_list arg_list = { 1, &in_arg }; + acpi_status status = AE_OK; + + in_arg.integer.value = acpi_state; + status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + /* + * OS can't evaluate the _TTS object correctly. Some warning + * message will be printed. But it won't break anything. + */ + printk(KERN_NOTICE "Failure in evaluating _TTS object\n"); + } +} + +static int tts_notify_reboot(struct notifier_block *this, + unsigned long code, void *x) +{ + acpi_sleep_tts_switch(ACPI_STATE_S5); + return NOTIFY_DONE; +} + +static struct notifier_block tts_notifier = { + .notifier_call = tts_notify_reboot, + .next = NULL, + .priority = 0, +}; + +static int acpi_sleep_prepare(u32 acpi_state) +{ +#ifdef CONFIG_ACPI_SLEEP + /* do we have a wakeup address for S2 and S3? */ + if (acpi_state == ACPI_STATE_S3) { + if (!acpi_wakeup_address) { + return -EFAULT; + } + acpi_set_firmware_waking_vector( + (acpi_physical_address)acpi_wakeup_address); + + } + ACPI_FLUSH_CPU_CACHE(); + acpi_enable_wakeup_device_prep(acpi_state); +#endif + printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n", + acpi_state); + acpi_enter_sleep_state_prep(acpi_state); + return 0; +} + +#ifdef CONFIG_ACPI_SLEEP +static u32 acpi_target_sleep_state = ACPI_STATE_S0; +/* + * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the + * user to request that behavior by using the 'acpi_old_suspend_ordering' + * kernel command line option that causes the following variable to be set. + */ +static bool old_suspend_ordering; + +void __init acpi_old_suspend_ordering(void) +{ + old_suspend_ordering = true; +} + +/* + * According to the ACPI specification the BIOS should make sure that ACPI is + * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, + * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI + * on such systems during resume. Unfortunately that doesn't help in + * particularly pathological cases in which SCI_EN has to be set directly on + * resume, although the specification states very clearly that this flag is + * owned by the hardware. The set_sci_en_on_resume variable will be set in such + * cases. + */ +static bool set_sci_en_on_resume; + +/** + * acpi_pm_disable_gpes - Disable the GPEs. + */ +static int acpi_pm_disable_gpes(void) +{ + acpi_disable_all_gpes(); + return 0; +} + +/** + * __acpi_pm_prepare - Prepare the platform to enter the target state. + * + * If necessary, set the firmware waking vector and do arch-specific + * nastiness to get the wakeup code to the waking vector. + */ +static int __acpi_pm_prepare(void) +{ + int error = acpi_sleep_prepare(acpi_target_sleep_state); + + if (error) + acpi_target_sleep_state = ACPI_STATE_S0; + return error; +} + +/** + * acpi_pm_prepare - Prepare the platform to enter the target sleep + * state and disable the GPEs. + */ +static int acpi_pm_prepare(void) +{ + int error = __acpi_pm_prepare(); + + if (!error) + acpi_disable_all_gpes(); + return error; +} + +/** + * acpi_pm_finish - Instruct the platform to leave a sleep state. + * + * This is called after we wake back up (or if entering the sleep state + * failed). + */ +static void acpi_pm_finish(void) +{ + u32 acpi_state = acpi_target_sleep_state; + + if (acpi_state == ACPI_STATE_S0) + return; + + printk(KERN_INFO PREFIX "Waking up from system sleep state S%d\n", + acpi_state); + acpi_disable_wakeup_device(acpi_state); + acpi_leave_sleep_state(acpi_state); + + /* reset firmware waking vector */ + acpi_set_firmware_waking_vector((acpi_physical_address) 0); + + acpi_target_sleep_state = ACPI_STATE_S0; +} + +/** + * acpi_pm_end - Finish up suspend sequence. + */ +static void acpi_pm_end(void) +{ + /* + * This is necessary in case acpi_pm_finish() is not called during a + * failing transition to a sleep state. + */ + acpi_target_sleep_state = ACPI_STATE_S0; + acpi_sleep_tts_switch(acpi_target_sleep_state); +} +#else /* !CONFIG_ACPI_SLEEP */ +#define acpi_target_sleep_state ACPI_STATE_S0 +#endif /* CONFIG_ACPI_SLEEP */ + +#ifdef CONFIG_SUSPEND +extern void do_suspend_lowlevel(void); + +static u32 acpi_suspend_states[] = { + [PM_SUSPEND_ON] = ACPI_STATE_S0, + [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, + [PM_SUSPEND_MEM] = ACPI_STATE_S3, + [PM_SUSPEND_MAX] = ACPI_STATE_S5 +}; + +/** + * acpi_suspend_begin - Set the target system sleep state to the state + * associated with given @pm_state, if supported. + */ +static int acpi_suspend_begin(suspend_state_t pm_state) +{ + u32 acpi_state = acpi_suspend_states[pm_state]; + int error = 0; + + if (sleep_states[acpi_state]) { + acpi_target_sleep_state = acpi_state; + acpi_sleep_tts_switch(acpi_target_sleep_state); + } else { + printk(KERN_ERR "ACPI does not support this state: %d\n", + pm_state); + error = -ENOSYS; + } + return error; +} + +/** + * acpi_suspend_enter - Actually enter a sleep state. + * @pm_state: ignored + * + * Flush caches and go to sleep. For STR we have to call arch-specific + * assembly, which in turn call acpi_enter_sleep_state(). + * It's unfortunate, but it works. Please fix if you're feeling frisky. + */ +static int acpi_suspend_enter(suspend_state_t pm_state) +{ + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 acpi_state = acpi_target_sleep_state; + + ACPI_FLUSH_CPU_CACHE(); + + /* Do arch specific saving of state. */ + if (acpi_state == ACPI_STATE_S3) { + int error = acpi_save_state_mem(); + + if (error) + return error; + } + + local_irq_save(flags); + acpi_enable_wakeup_device(acpi_state); + switch (acpi_state) { + case ACPI_STATE_S1: + barrier(); + status = acpi_enter_sleep_state(acpi_state); + break; + + case ACPI_STATE_S3: + do_suspend_lowlevel(); + break; + } + + /* If ACPI is not enabled by the BIOS, we need to enable it here. */ + if (set_sci_en_on_resume) + acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1); + else + acpi_enable(); + + /* Reprogram control registers and execute _BFS */ + acpi_leave_sleep_state_prep(acpi_state); + + /* ACPI 3.0 specs (P62) says that it's the responsibility + * of the OSPM to clear the status bit [ implying that the + * POWER_BUTTON event should not reach userspace ] + */ + if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) + acpi_clear_event(ACPI_EVENT_POWER_BUTTON); + + /* + * Disable and clear GPE status before interrupt is enabled. Some GPEs + * (like wakeup GPE) haven't handler, this can avoid such GPE misfire. + * acpi_leave_sleep_state will reenable specific GPEs later + */ + acpi_disable_all_gpes(); + + local_irq_restore(flags); + printk(KERN_DEBUG "Back to C!\n"); + + /* restore processor state */ + if (acpi_state == ACPI_STATE_S3) + acpi_restore_state_mem(); + + return ACPI_SUCCESS(status) ? 0 : -EFAULT; +} + +static int acpi_suspend_state_valid(suspend_state_t pm_state) +{ + u32 acpi_state; + + switch (pm_state) { + case PM_SUSPEND_ON: + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + acpi_state = acpi_suspend_states[pm_state]; + + return sleep_states[acpi_state]; + default: + return 0; + } +} + +static struct platform_suspend_ops acpi_suspend_ops = { + .valid = acpi_suspend_state_valid, + .begin = acpi_suspend_begin, + .prepare = acpi_pm_prepare, + .enter = acpi_suspend_enter, + .finish = acpi_pm_finish, + .end = acpi_pm_end, +}; + +/** + * acpi_suspend_begin_old - Set the target system sleep state to the + * state associated with given @pm_state, if supported, and + * execute the _PTS control method. This function is used if the + * pre-ACPI 2.0 suspend ordering has been requested. + */ +static int acpi_suspend_begin_old(suspend_state_t pm_state) +{ + int error = acpi_suspend_begin(pm_state); + + if (!error) + error = __acpi_pm_prepare(); + return error; +} + +/* + * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has + * been requested. + */ +static struct platform_suspend_ops acpi_suspend_ops_old = { + .valid = acpi_suspend_state_valid, + .begin = acpi_suspend_begin_old, + .prepare = acpi_pm_disable_gpes, + .enter = acpi_suspend_enter, + .finish = acpi_pm_finish, + .end = acpi_pm_end, + .recover = acpi_pm_finish, +}; + +static int __init init_old_suspend_ordering(const struct dmi_system_id *d) +{ + old_suspend_ordering = true; + return 0; +} + +static int __init init_set_sci_en_on_resume(const struct dmi_system_id *d) +{ + set_sci_en_on_resume = true; + return 0; +} + +static struct dmi_system_id __initdata acpisleep_dmi_table[] = { + { + .callback = init_old_suspend_ordering, + .ident = "Abit KN9 (nForce4 variant)", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"), + DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "HP xw4600 Workstation", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), + }, + }, + { + .callback = init_set_sci_en_on_resume, + .ident = "Apple MacBook 1,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), + }, + }, + { + .callback = init_set_sci_en_on_resume, + .ident = "Apple MacMini 1,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), + }, + }, + {}, +}; +#endif /* CONFIG_SUSPEND */ + +#ifdef CONFIG_HIBERNATION +static unsigned long s4_hardware_signature; +static struct acpi_table_facs *facs; +static bool nosigcheck; + +void __init acpi_no_s4_hw_signature(void) +{ + nosigcheck = true; +} + +static int acpi_hibernation_begin(void) +{ + acpi_target_sleep_state = ACPI_STATE_S4; + acpi_sleep_tts_switch(acpi_target_sleep_state); + return 0; +} + +static int acpi_hibernation_enter(void) +{ + acpi_status status = AE_OK; + unsigned long flags = 0; + + ACPI_FLUSH_CPU_CACHE(); + + local_irq_save(flags); + acpi_enable_wakeup_device(ACPI_STATE_S4); + /* This shouldn't return. If it returns, we have a problem */ + status = acpi_enter_sleep_state(ACPI_STATE_S4); + /* Reprogram control registers and execute _BFS */ + acpi_leave_sleep_state_prep(ACPI_STATE_S4); + local_irq_restore(flags); + + return ACPI_SUCCESS(status) ? 0 : -EFAULT; +} + +static void acpi_hibernation_leave(void) +{ + /* + * If ACPI is not enabled by the BIOS and the boot kernel, we need to + * enable it here. + */ + acpi_enable(); + /* Reprogram control registers and execute _BFS */ + acpi_leave_sleep_state_prep(ACPI_STATE_S4); + /* Check the hardware signature */ + if (facs && s4_hardware_signature != facs->hardware_signature) { + printk(KERN_EMERG "ACPI: Hardware changed while hibernated, " + "cannot resume!\n"); + panic("ACPI S4 hardware signature mismatch"); + } +} + +static void acpi_pm_enable_gpes(void) +{ + acpi_enable_all_runtime_gpes(); +} + +static struct platform_hibernation_ops acpi_hibernation_ops = { + .begin = acpi_hibernation_begin, + .end = acpi_pm_end, + .pre_snapshot = acpi_pm_prepare, + .finish = acpi_pm_finish, + .prepare = acpi_pm_prepare, + .enter = acpi_hibernation_enter, + .leave = acpi_hibernation_leave, + .pre_restore = acpi_pm_disable_gpes, + .restore_cleanup = acpi_pm_enable_gpes, +}; + +/** + * acpi_hibernation_begin_old - Set the target system sleep state to + * ACPI_STATE_S4 and execute the _PTS control method. This + * function is used if the pre-ACPI 2.0 suspend ordering has been + * requested. + */ +static int acpi_hibernation_begin_old(void) +{ + int error; + /* + * The _TTS object should always be evaluated before the _PTS object. + * When the old_suspended_ordering is true, the _PTS object is + * evaluated in the acpi_sleep_prepare. + */ + acpi_sleep_tts_switch(ACPI_STATE_S4); + + error = acpi_sleep_prepare(ACPI_STATE_S4); + + if (!error) + acpi_target_sleep_state = ACPI_STATE_S4; + return error; +} + +/* + * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has + * been requested. + */ +static struct platform_hibernation_ops acpi_hibernation_ops_old = { + .begin = acpi_hibernation_begin_old, + .end = acpi_pm_end, + .pre_snapshot = acpi_pm_disable_gpes, + .finish = acpi_pm_finish, + .prepare = acpi_pm_disable_gpes, + .enter = acpi_hibernation_enter, + .leave = acpi_hibernation_leave, + .pre_restore = acpi_pm_disable_gpes, + .restore_cleanup = acpi_pm_enable_gpes, + .recover = acpi_pm_finish, +}; +#endif /* CONFIG_HIBERNATION */ + +int acpi_suspend(u32 acpi_state) +{ + suspend_state_t states[] = { + [1] = PM_SUSPEND_STANDBY, + [3] = PM_SUSPEND_MEM, + [5] = PM_SUSPEND_MAX + }; + + if (acpi_state < 6 && states[acpi_state]) + return pm_suspend(states[acpi_state]); + if (acpi_state == 4) + return hibernate(); + return -EINVAL; +} + +#ifdef CONFIG_PM_SLEEP +/** + * acpi_pm_device_sleep_state - return preferred power state of ACPI device + * in the system sleep state given by %acpi_target_sleep_state + * @dev: device to examine; its driver model wakeup flags control + * whether it should be able to wake up the system + * @d_min_p: used to store the upper limit of allowed states range + * Return value: preferred power state of the device on success, -ENODEV on + * failure (ie. if there's no 'struct acpi_device' for @dev) + * + * Find the lowest power (highest number) ACPI device power state that + * device @dev can be in while the system is in the sleep state represented + * by %acpi_target_sleep_state. If @wake is nonzero, the device should be + * able to wake up the system from this sleep state. If @d_min_p is set, + * the highest power (lowest number) device power state of @dev allowed + * in this system sleep state is stored at the location pointed to by it. + * + * The caller must ensure that @dev is valid before using this function. + * The caller is also responsible for figuring out if the device is + * supposed to be able to wake up the system and passing this information + * via @wake. + */ + +int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) +{ + acpi_handle handle = DEVICE_ACPI_HANDLE(dev); + struct acpi_device *adev; + char acpi_method[] = "_SxD"; + unsigned long long d_min, d_max; + + if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { + printk(KERN_DEBUG "ACPI handle has no context!\n"); + return -ENODEV; + } + + acpi_method[2] = '0' + acpi_target_sleep_state; + /* + * If the sleep state is S0, we will return D3, but if the device has + * _S0W, we will use the value from _S0W + */ + d_min = ACPI_STATE_D0; + d_max = ACPI_STATE_D3; + + /* + * If present, _SxD methods return the minimum D-state (highest power + * state) we can use for the corresponding S-states. Otherwise, the + * minimum D-state is D0 (ACPI 3.x). + * + * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer + * provided -- that's our fault recovery, we ignore retval. + */ + if (acpi_target_sleep_state > ACPI_STATE_S0) + acpi_evaluate_integer(handle, acpi_method, NULL, &d_min); + + /* + * If _PRW says we can wake up the system from the target sleep state, + * the D-state returned by _SxD is sufficient for that (we assume a + * wakeup-aware driver if wake is set). Still, if _SxW exists + * (ACPI 3.x), it should return the maximum (lowest power) D-state that + * can wake the system. _S0W may be valid, too. + */ + if (acpi_target_sleep_state == ACPI_STATE_S0 || + (device_may_wakeup(dev) && adev->wakeup.state.enabled && + adev->wakeup.sleep_state <= acpi_target_sleep_state)) { + acpi_status status; + + acpi_method[3] = 'W'; + status = acpi_evaluate_integer(handle, acpi_method, NULL, + &d_max); + if (ACPI_FAILURE(status)) { + d_max = d_min; + } else if (d_max < d_min) { + /* Warn the user of the broken DSDT */ + printk(KERN_WARNING "ACPI: Wrong value from %s\n", + acpi_method); + /* Sanitize it */ + d_min = d_max; + } + } + + if (d_min_p) + *d_min_p = d_min; + return d_max; +} + +/** + * acpi_pm_device_sleep_wake - enable or disable the system wake-up + * capability of given device + * @dev: device to handle + * @enable: 'true' - enable, 'false' - disable the wake-up capability + */ +int acpi_pm_device_sleep_wake(struct device *dev, bool enable) +{ + acpi_handle handle; + struct acpi_device *adev; + + if (!device_may_wakeup(dev)) + return -EINVAL; + + handle = DEVICE_ACPI_HANDLE(dev); + if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { + printk(KERN_DEBUG "ACPI handle has no context!\n"); + return -ENODEV; + } + + return enable ? + acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) : + acpi_disable_wakeup_device_power(adev); +} +#endif + +static void acpi_power_off_prepare(void) +{ + /* Prepare to power off the system */ + acpi_sleep_prepare(ACPI_STATE_S5); + acpi_disable_all_gpes(); +} + +static void acpi_power_off(void) +{ + /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ + printk("%s called\n", __func__); + local_irq_disable(); + acpi_enable_wakeup_device(ACPI_STATE_S5); + acpi_enter_sleep_state(ACPI_STATE_S5); +} + +int __init acpi_sleep_init(void) +{ + acpi_status status; + u8 type_a, type_b; +#ifdef CONFIG_SUSPEND + int i = 0; + + dmi_check_system(acpisleep_dmi_table); +#endif + + if (acpi_disabled) + return 0; + + sleep_states[ACPI_STATE_S0] = 1; + printk(KERN_INFO PREFIX "(supports S0"); + +#ifdef CONFIG_SUSPEND + for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) { + status = acpi_get_sleep_type_data(i, &type_a, &type_b); + if (ACPI_SUCCESS(status)) { + sleep_states[i] = 1; + printk(" S%d", i); + } + } + + suspend_set_ops(old_suspend_ordering ? + &acpi_suspend_ops_old : &acpi_suspend_ops); +#endif + +#ifdef CONFIG_HIBERNATION + status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); + if (ACPI_SUCCESS(status)) { + hibernation_set_ops(old_suspend_ordering ? + &acpi_hibernation_ops_old : &acpi_hibernation_ops); + sleep_states[ACPI_STATE_S4] = 1; + printk(" S4"); + if (!nosigcheck) { + acpi_get_table(ACPI_SIG_FACS, 1, + (struct acpi_table_header **)&facs); + if (facs) + s4_hardware_signature = + facs->hardware_signature; + } + } +#endif + status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); + if (ACPI_SUCCESS(status)) { + sleep_states[ACPI_STATE_S5] = 1; + printk(" S5"); + pm_power_off_prepare = acpi_power_off_prepare; + pm_power_off = acpi_power_off; + } + printk(")\n"); + /* + * Register the tts_notifier to reboot notifier list so that the _TTS + * object can also be evaluated when the system enters S5. + */ + register_reboot_notifier(&tts_notifier); + return 0; +} diff --git a/drivers/acpi/namespace/Makefile b/drivers/acpi/namespace/Makefile deleted file mode 100644 index 371a2daf837f..000000000000 --- a/drivers/acpi/namespace/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -obj-y := nsaccess.o nsload.o nssearch.o nsxfeval.o \ - nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ - nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ - nsparse.o nspredef.o - -obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o - -EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c deleted file mode 100644 index 7954640e69cb..000000000000 --- a/drivers/acpi/namespace/nsaccess.c +++ /dev/null @@ -1,676 +0,0 @@ -/******************************************************************************* - * - * Module Name: nsaccess - Top-level functions for accessing ACPI namespace - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsaccess") - -/******************************************************************************* - * - * FUNCTION: acpi_ns_root_initialize - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Allocate and initialize the default root named objects - * - * MUTEX: Locks namespace for entire execution - * - ******************************************************************************/ -acpi_status acpi_ns_root_initialize(void) -{ - acpi_status status; - const struct acpi_predefined_names *init_val = NULL; - struct acpi_namespace_node *new_node; - union acpi_operand_object *obj_desc; - acpi_string val = NULL; - - ACPI_FUNCTION_TRACE(ns_root_initialize); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * The global root ptr is initially NULL, so a non-NULL value indicates - * that acpi_ns_root_initialize() has already been called; just return. - */ - if (acpi_gbl_root_node) { - status = AE_OK; - goto unlock_and_exit; - } - - /* - * Tell the rest of the subsystem that the root is initialized - * (This is OK because the namespace is locked) - */ - acpi_gbl_root_node = &acpi_gbl_root_node_struct; - - /* Enter the pre-defined names in the name table */ - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Entering predefined entries into namespace\n")); - - for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { - - /* _OSI is optional for now, will be permanent later */ - - if (!ACPI_STRCMP(init_val->name, "_OSI") - && !acpi_gbl_create_osi_method) { - continue; - } - - status = acpi_ns_lookup(NULL, init_val->name, init_val->type, - ACPI_IMODE_LOAD_PASS2, - ACPI_NS_NO_UPSEARCH, NULL, &new_node); - - if (ACPI_FAILURE(status) || (!new_node)) { /* Must be on same line for code converter */ - ACPI_EXCEPTION((AE_INFO, status, - "Could not create predefined name %s", - init_val->name)); - } - - /* - * Name entered successfully. - * If entry in pre_defined_names[] specifies an - * initial value, create the initial value. - */ - if (init_val->val) { - status = acpi_os_predefined_override(init_val, &val); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not override predefined %s", - init_val->name)); - } - - if (!val) { - val = init_val->val; - } - - /* - * Entry requests an initial value, allocate a - * descriptor for it. - */ - obj_desc = - acpi_ut_create_internal_object(init_val->type); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - /* - * Convert value string from table entry to - * internal representation. Only types actually - * used for initial values are implemented here. - */ - switch (init_val->type) { - case ACPI_TYPE_METHOD: - obj_desc->method.param_count = - (u8) ACPI_TO_INTEGER(val); - obj_desc->common.flags |= AOPOBJ_DATA_VALID; - -#if defined (ACPI_ASL_COMPILER) - - /* Save the parameter count for the i_aSL compiler */ - - new_node->value = obj_desc->method.param_count; -#else - /* Mark this as a very SPECIAL method */ - - obj_desc->method.method_flags = - AML_METHOD_INTERNAL_ONLY; - obj_desc->method.implementation = - acpi_ut_osi_implementation; -#endif - break; - - case ACPI_TYPE_INTEGER: - - obj_desc->integer.value = ACPI_TO_INTEGER(val); - break; - - case ACPI_TYPE_STRING: - - /* - * Build an object around the static string - */ - obj_desc->string.length = - (u32) ACPI_STRLEN(val); - obj_desc->string.pointer = val; - obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; - break; - - case ACPI_TYPE_MUTEX: - - obj_desc->mutex.node = new_node; - obj_desc->mutex.sync_level = - (u8) (ACPI_TO_INTEGER(val) - 1); - - /* Create a mutex */ - - status = - acpi_os_create_mutex(&obj_desc->mutex. - os_mutex); - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(obj_desc); - goto unlock_and_exit; - } - - /* Special case for ACPI Global Lock */ - - if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { - acpi_gbl_global_lock_mutex = obj_desc; - - /* Create additional counting semaphore for global lock */ - - status = - acpi_os_create_semaphore(1, 0, - &acpi_gbl_global_lock_semaphore); - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference - (obj_desc); - goto unlock_and_exit; - } - } - break; - - default: - - ACPI_ERROR((AE_INFO, - "Unsupported initial type value %X", - init_val->type)); - acpi_ut_remove_reference(obj_desc); - obj_desc = NULL; - continue; - } - - /* Store pointer to value descriptor in the Node */ - - status = acpi_ns_attach_object(new_node, obj_desc, - ACPI_GET_OBJECT_TYPE - (obj_desc)); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - } - } - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - - /* Save a handle to "_GPE", it is always present */ - - if (ACPI_SUCCESS(status)) { - status = acpi_ns_get_node(NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, - &acpi_gbl_fadt_gpe_device); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_lookup - * - * PARAMETERS: scope_info - Current scope info block - * Pathname - Search pathname, in internal format - * (as represented in the AML stream) - * Type - Type associated with name - * interpreter_mode - IMODE_LOAD_PASS2 => add name if not found - * Flags - Flags describing the search restrictions - * walk_state - Current state of the walk - * return_node - Where the Node is placed (if found - * or created successfully) - * - * RETURN: Status - * - * DESCRIPTION: Find or enter the passed name in the name space. - * Log an error if name not found in Exec mode. - * - * MUTEX: Assumes namespace is locked. - * - ******************************************************************************/ - -acpi_status -acpi_ns_lookup(union acpi_generic_state *scope_info, - char *pathname, - acpi_object_type type, - acpi_interpreter_mode interpreter_mode, - u32 flags, - struct acpi_walk_state *walk_state, - struct acpi_namespace_node **return_node) -{ - acpi_status status; - char *path = pathname; - struct acpi_namespace_node *prefix_node; - struct acpi_namespace_node *current_node = NULL; - struct acpi_namespace_node *this_node = NULL; - u32 num_segments; - u32 num_carats; - acpi_name simple_name; - acpi_object_type type_to_check_for; - acpi_object_type this_search_type; - u32 search_parent_flag = ACPI_NS_SEARCH_PARENT; - u32 local_flags; - - ACPI_FUNCTION_TRACE(ns_lookup); - - if (!return_node) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); - *return_node = ACPI_ENTRY_NOT_FOUND; - acpi_gbl_ns_lookup_count++; - - if (!acpi_gbl_root_node) { - return_ACPI_STATUS(AE_NO_NAMESPACE); - } - - /* - * Get the prefix scope. - * A null scope means use the root scope - */ - if ((!scope_info) || (!scope_info->scope.node)) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Null scope prefix, using root node (%p)\n", - acpi_gbl_root_node)); - - prefix_node = acpi_gbl_root_node; - } else { - prefix_node = scope_info->scope.node; - if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) != - ACPI_DESC_TYPE_NAMED) { - ACPI_ERROR((AE_INFO, "%p is not a namespace node [%s]", - prefix_node, - acpi_ut_get_descriptor_name(prefix_node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) { - /* - * This node might not be a actual "scope" node (such as a - * Device/Method, etc.) It could be a Package or other object node. - * Backup up the tree to find the containing scope node. - */ - while (!acpi_ns_opens_scope(prefix_node->type) && - prefix_node->type != ACPI_TYPE_ANY) { - prefix_node = - acpi_ns_get_parent_node(prefix_node); - } - } - } - - /* Save type TBD: may be no longer necessary */ - - type_to_check_for = type; - - /* - * Begin examination of the actual pathname - */ - if (!pathname) { - - /* A Null name_path is allowed and refers to the root */ - - num_segments = 0; - this_node = acpi_gbl_root_node; - path = ""; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Null Pathname (Zero segments), Flags=%X\n", - flags)); - } else { - /* - * Name pointer is valid (and must be in internal name format) - * - * Check for scope prefixes: - * - * As represented in the AML stream, a namepath consists of an - * optional scope prefix followed by a name segment part. - * - * If present, the scope prefix is either a Root Prefix (in - * which case the name is fully qualified), or one or more - * Parent Prefixes (in which case the name's scope is relative - * to the current scope). - */ - if (*path == (u8) AML_ROOT_PREFIX) { - - /* Pathname is fully qualified, start from the root */ - - this_node = acpi_gbl_root_node; - search_parent_flag = ACPI_NS_NO_UPSEARCH; - - /* Point to name segment part */ - - path++; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Path is absolute from root [%p]\n", - this_node)); - } else { - /* Pathname is relative to current scope, start there */ - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Searching relative to prefix scope [%4.4s] (%p)\n", - acpi_ut_get_node_name(prefix_node), - prefix_node)); - - /* - * Handle multiple Parent Prefixes (carat) by just getting - * the parent node for each prefix instance. - */ - this_node = prefix_node; - num_carats = 0; - while (*path == (u8) AML_PARENT_PREFIX) { - - /* Name is fully qualified, no search rules apply */ - - search_parent_flag = ACPI_NS_NO_UPSEARCH; - /* - * Point past this prefix to the name segment - * part or the next Parent Prefix - */ - path++; - - /* Backup to the parent node */ - - num_carats++; - this_node = acpi_ns_get_parent_node(this_node); - if (!this_node) { - - /* Current scope has no parent scope */ - - ACPI_ERROR((AE_INFO, - "ACPI path has too many parent prefixes (^) - reached beyond root node")); - return_ACPI_STATUS(AE_NOT_FOUND); - } - } - - if (search_parent_flag == ACPI_NS_NO_UPSEARCH) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Search scope is [%4.4s], path has %d carat(s)\n", - acpi_ut_get_node_name - (this_node), num_carats)); - } - } - - /* - * Determine the number of ACPI name segments in this pathname. - * - * The segment part consists of either: - * - A Null name segment (0) - * - A dual_name_prefix followed by two 4-byte name segments - * - A multi_name_prefix followed by a byte indicating the - * number of segments and the segments themselves. - * - A single 4-byte name segment - * - * Examine the name prefix opcode, if any, to determine the number of - * segments. - */ - switch (*path) { - case 0: - /* - * Null name after a root or parent prefixes. We already - * have the correct target node and there are no name segments. - */ - num_segments = 0; - type = this_node->type; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Prefix-only Pathname (Zero name segments), Flags=%X\n", - flags)); - break; - - case AML_DUAL_NAME_PREFIX: - - /* More than one name_seg, search rules do not apply */ - - search_parent_flag = ACPI_NS_NO_UPSEARCH; - - /* Two segments, point to first name segment */ - - num_segments = 2; - path++; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Dual Pathname (2 segments, Flags=%X)\n", - flags)); - break; - - case AML_MULTI_NAME_PREFIX_OP: - - /* More than one name_seg, search rules do not apply */ - - search_parent_flag = ACPI_NS_NO_UPSEARCH; - - /* Extract segment count, point to first name segment */ - - path++; - num_segments = (u32) (u8) * path; - path++; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Multi Pathname (%d Segments, Flags=%X)\n", - num_segments, flags)); - break; - - default: - /* - * Not a Null name, no Dual or Multi prefix, hence there is - * only one name segment and Pathname is already pointing to it. - */ - num_segments = 1; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Simple Pathname (1 segment, Flags=%X)\n", - flags)); - break; - } - - ACPI_DEBUG_EXEC(acpi_ns_print_pathname(num_segments, path)); - } - - /* - * Search namespace for each segment of the name. Loop through and - * verify (or add to the namespace) each name segment. - * - * The object type is significant only at the last name - * segment. (We don't care about the types along the path, only - * the type of the final target object.) - */ - this_search_type = ACPI_TYPE_ANY; - current_node = this_node; - while (num_segments && current_node) { - num_segments--; - if (!num_segments) { - /* - * This is the last segment, enable typechecking - */ - this_search_type = type; - - /* - * Only allow automatic parent search (search rules) if the caller - * requested it AND we have a single, non-fully-qualified name_seg - */ - if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) && - (flags & ACPI_NS_SEARCH_PARENT)) { - local_flags |= ACPI_NS_SEARCH_PARENT; - } - - /* Set error flag according to caller */ - - if (flags & ACPI_NS_ERROR_IF_FOUND) { - local_flags |= ACPI_NS_ERROR_IF_FOUND; - } - } - - /* Extract one ACPI name from the front of the pathname */ - - ACPI_MOVE_32_TO_32(&simple_name, path); - - /* Try to find the single (4 character) ACPI name */ - - status = - acpi_ns_search_and_enter(simple_name, walk_state, - current_node, interpreter_mode, - this_search_type, local_flags, - &this_node); - if (ACPI_FAILURE(status)) { - if (status == AE_NOT_FOUND) { - - /* Name not found in ACPI namespace */ - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Name [%4.4s] not found in scope [%4.4s] %p\n", - (char *)&simple_name, - (char *)¤t_node->name, - current_node)); - } - - *return_node = this_node; - return_ACPI_STATUS(status); - } - - /* More segments to follow? */ - - if (num_segments > 0) { - /* - * If we have an alias to an object that opens a scope (such as a - * device or processor), we need to dereference the alias here so that - * we can access any children of the original node (via the remaining - * segments). - */ - if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) { - if (!this_node->object) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - if (acpi_ns_opens_scope - (((struct acpi_namespace_node *)this_node-> - object)->type)) { - this_node = - (struct acpi_namespace_node *) - this_node->object; - } - } - } - - /* Special handling for the last segment (num_segments == 0) */ - - else { - /* - * Sanity typecheck of the target object: - * - * If 1) This is the last segment (num_segments == 0) - * 2) And we are looking for a specific type - * (Not checking for TYPE_ANY) - * 3) Which is not an alias - * 4) Which is not a local type (TYPE_SCOPE) - * 5) And the type of target object is known (not TYPE_ANY) - * 6) And target object does not match what we are looking for - * - * Then we have a type mismatch. Just warn and ignore it. - */ - if ((type_to_check_for != ACPI_TYPE_ANY) && - (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && - (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) - && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) - && (this_node->type != ACPI_TYPE_ANY) - && (this_node->type != type_to_check_for)) { - - /* Complain about a type mismatch */ - - ACPI_WARNING((AE_INFO, - "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", - ACPI_CAST_PTR(char, &simple_name), - acpi_ut_get_type_name(this_node-> - type), - acpi_ut_get_type_name - (type_to_check_for))); - } - - /* - * If this is the last name segment and we are not looking for a - * specific type, but the type of found object is known, use that type - * to (later) see if it opens a scope. - */ - if (type == ACPI_TYPE_ANY) { - type = this_node->type; - } - } - - /* Point to next name segment and make this node current */ - - path += ACPI_NAME_SIZE; - current_node = this_node; - } - - /* - * Always check if we need to open a new scope - */ - if (!(flags & ACPI_NS_DONT_OPEN_SCOPE) && (walk_state)) { - /* - * If entry is a type which opens a scope, push the new scope on the - * scope stack. - */ - if (acpi_ns_opens_scope(type)) { - status = - acpi_ds_scope_stack_push(this_node, type, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - } - - *return_node = this_node; - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c deleted file mode 100644 index cb2afbf4e457..000000000000 --- a/drivers/acpi/namespace/nsalloc.c +++ /dev/null @@ -1,497 +0,0 @@ -/******************************************************************************* - * - * Module Name: nsalloc - Namespace allocation and deletion utilities - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsalloc") - -/******************************************************************************* - * - * FUNCTION: acpi_ns_create_node - * - * PARAMETERS: Name - Name of the new node (4 char ACPI name) - * - * RETURN: New namespace node (Null on failure) - * - * DESCRIPTION: Create a namespace node - * - ******************************************************************************/ -struct acpi_namespace_node *acpi_ns_create_node(u32 name) -{ - struct acpi_namespace_node *node; -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - u32 temp; -#endif - - ACPI_FUNCTION_TRACE(ns_create_node); - - node = acpi_os_acquire_object(acpi_gbl_namespace_cache); - if (!node) { - return_PTR(NULL); - } - - ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++); - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - temp = - acpi_gbl_ns_node_list->total_allocated - - acpi_gbl_ns_node_list->total_freed; - if (temp > acpi_gbl_ns_node_list->max_occupied) { - acpi_gbl_ns_node_list->max_occupied = temp; - } -#endif - - node->name.integer = name; - ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED); - return_PTR(node); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_delete_node - * - * PARAMETERS: Node - Node to be deleted - * - * RETURN: None - * - * DESCRIPTION: Delete a namespace node - * - ******************************************************************************/ - -void acpi_ns_delete_node(struct acpi_namespace_node *node) -{ - struct acpi_namespace_node *parent_node; - struct acpi_namespace_node *prev_node; - struct acpi_namespace_node *next_node; - - ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node); - - parent_node = acpi_ns_get_parent_node(node); - - prev_node = NULL; - next_node = parent_node->child; - - /* Find the node that is the previous peer in the parent's child list */ - - while (next_node != node) { - prev_node = next_node; - next_node = prev_node->peer; - } - - if (prev_node) { - - /* Node is not first child, unlink it */ - - prev_node->peer = next_node->peer; - if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { - prev_node->flags |= ANOBJ_END_OF_PEER_LIST; - } - } else { - /* Node is first child (has no previous peer) */ - - if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { - - /* No peers at all */ - - parent_node->child = NULL; - } else { /* Link peer list to parent */ - - parent_node->child = next_node->peer; - } - } - - ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); - - /* - * Detach an object if there is one, then delete the node - */ - acpi_ns_detach_object(node); - (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_install_node - * - * PARAMETERS: walk_state - Current state of the walk - * parent_node - The parent of the new Node - * Node - The new Node to install - * Type - ACPI object type of the new Node - * - * RETURN: None - * - * DESCRIPTION: Initialize a new namespace node and install it amongst - * its peers. - * - * Note: Current namespace lookup is linear search. This appears - * to be sufficient as namespace searches consume only a small - * fraction of the execution time of the ACPI subsystem. - * - ******************************************************************************/ - -void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namespace_node *parent_node, /* Parent */ - struct acpi_namespace_node *node, /* New Child */ - acpi_object_type type) -{ - acpi_owner_id owner_id = 0; - struct acpi_namespace_node *child_node; - - ACPI_FUNCTION_TRACE(ns_install_node); - - /* - * Get the owner ID from the Walk state - * The owner ID is used to track table deletion and - * deletion of objects created by methods - */ - if (walk_state) { - owner_id = walk_state->owner_id; - } - - /* Link the new entry into the parent and existing children */ - - child_node = parent_node->child; - if (!child_node) { - parent_node->child = node; - node->flags |= ANOBJ_END_OF_PEER_LIST; - node->peer = parent_node; - } else { - while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) { - child_node = child_node->peer; - } - - child_node->peer = node; - - /* Clear end-of-list flag */ - - child_node->flags &= ~ANOBJ_END_OF_PEER_LIST; - node->flags |= ANOBJ_END_OF_PEER_LIST; - node->peer = parent_node; - } - - /* Init the new entry */ - - node->owner_id = owner_id; - node->type = (u8) type; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n", - acpi_ut_get_node_name(node), - acpi_ut_get_type_name(node->type), node, owner_id, - acpi_ut_get_node_name(parent_node), - acpi_ut_get_type_name(parent_node->type), - parent_node)); - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_delete_children - * - * PARAMETERS: parent_node - Delete this objects children - * - * RETURN: None. - * - * DESCRIPTION: Delete all children of the parent object. In other words, - * deletes a "scope". - * - ******************************************************************************/ - -void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) -{ - struct acpi_namespace_node *child_node; - struct acpi_namespace_node *next_node; - u8 flags; - - ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node); - - if (!parent_node) { - return_VOID; - } - - /* If no children, all done! */ - - child_node = parent_node->child; - if (!child_node) { - return_VOID; - } - - /* - * Deallocate all children at this level - */ - do { - - /* Get the things we need */ - - next_node = child_node->peer; - flags = child_node->flags; - - /* Grandchildren should have all been deleted already */ - - if (child_node->child) { - ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p", - parent_node, child_node)); - } - - /* Now we can free this child object */ - - ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Object %p, Remaining %X\n", child_node, - acpi_gbl_current_node_count)); - - /* - * Detach an object if there is one, then free the child node - */ - acpi_ns_detach_object(child_node); - - /* Now we can delete the node */ - - (void)acpi_os_release_object(acpi_gbl_namespace_cache, - child_node); - - /* And move on to the next child in the list */ - - child_node = next_node; - - } while (!(flags & ANOBJ_END_OF_PEER_LIST)); - - /* Clear the parent's child pointer */ - - parent_node->child = NULL; - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_delete_namespace_subtree - * - * PARAMETERS: parent_node - Root of the subtree to be deleted - * - * RETURN: None. - * - * DESCRIPTION: Delete a subtree of the namespace. This includes all objects - * stored within the subtree. - * - ******************************************************************************/ - -void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) -{ - struct acpi_namespace_node *child_node = NULL; - u32 level = 1; - - ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree); - - if (!parent_node) { - return_VOID; - } - - /* - * Traverse the tree of objects until we bubble back up - * to where we started. - */ - while (level > 0) { - - /* Get the next node in this scope (NULL if none) */ - - child_node = - acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, - child_node); - if (child_node) { - - /* Found a child node - detach any attached object */ - - acpi_ns_detach_object(child_node); - - /* Check if this node has any children */ - - if (acpi_ns_get_next_node - (ACPI_TYPE_ANY, child_node, NULL)) { - /* - * There is at least one child of this node, - * visit the node - */ - level++; - parent_node = child_node; - child_node = NULL; - } - } else { - /* - * No more children of this parent node. - * Move up to the grandparent. - */ - level--; - - /* - * Now delete all of the children of this parent - * all at the same time. - */ - acpi_ns_delete_children(parent_node); - - /* New "last child" is this parent node */ - - child_node = parent_node; - - /* Move up the tree to the grandparent */ - - parent_node = acpi_ns_get_parent_node(parent_node); - } - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_delete_namespace_by_owner - * - * PARAMETERS: owner_id - All nodes with this owner will be deleted - * - * RETURN: Status - * - * DESCRIPTION: Delete entries within the namespace that are owned by a - * specific ID. Used to delete entire ACPI tables. All - * reference counts are updated. - * - * MUTEX: Locks namespace during deletion walk. - * - ******************************************************************************/ - -void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) -{ - struct acpi_namespace_node *child_node; - struct acpi_namespace_node *deletion_node; - struct acpi_namespace_node *parent_node; - u32 level; - acpi_status status; - - ACPI_FUNCTION_TRACE_U32(ns_delete_namespace_by_owner, owner_id); - - if (owner_id == 0) { - return_VOID; - } - - /* Lock namespace for possible update */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_VOID; - } - - deletion_node = NULL; - parent_node = acpi_gbl_root_node; - child_node = NULL; - level = 1; - - /* - * Traverse the tree of nodes until we bubble back up - * to where we started. - */ - while (level > 0) { - /* - * Get the next child of this parent node. When child_node is NULL, - * the first child of the parent is returned - */ - child_node = - acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, - child_node); - - if (deletion_node) { - acpi_ns_delete_children(deletion_node); - acpi_ns_delete_node(deletion_node); - deletion_node = NULL; - } - - if (child_node) { - if (child_node->owner_id == owner_id) { - - /* Found a matching child node - detach any attached object */ - - acpi_ns_detach_object(child_node); - } - - /* Check if this node has any children */ - - if (acpi_ns_get_next_node - (ACPI_TYPE_ANY, child_node, NULL)) { - /* - * There is at least one child of this node, - * visit the node - */ - level++; - parent_node = child_node; - child_node = NULL; - } else if (child_node->owner_id == owner_id) { - deletion_node = child_node; - } - } else { - /* - * No more children of this parent node. - * Move up to the grandparent. - */ - level--; - if (level != 0) { - if (parent_node->owner_id == owner_id) { - deletion_node = parent_node; - } - } - - /* New "last child" is this parent node */ - - child_node = parent_node; - - /* Move up the tree to the grandparent */ - - parent_node = acpi_ns_get_parent_node(parent_node); - } - } - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_VOID; -} diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c deleted file mode 100644 index 48f02e659f24..000000000000 --- a/drivers/acpi/namespace/nsdump.c +++ /dev/null @@ -1,709 +0,0 @@ -/****************************************************************************** - * - * Module Name: nsdump - table dumping routines for debug - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsdump") - -/* Local prototypes */ -#ifdef ACPI_OBSOLETE_FUNCTIONS -void acpi_ns_dump_root_devices(void); - -static acpi_status -acpi_ns_dump_one_device(acpi_handle obj_handle, - u32 level, void *context, void **return_value); -#endif - -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) -/******************************************************************************* - * - * FUNCTION: acpi_ns_print_pathname - * - * PARAMETERS: num_segments - Number of ACPI name segments - * Pathname - The compressed (internal) path - * - * RETURN: None - * - * DESCRIPTION: Print an object's full namespace pathname - * - ******************************************************************************/ - -void acpi_ns_print_pathname(u32 num_segments, char *pathname) -{ - u32 i; - - ACPI_FUNCTION_NAME(ns_print_pathname); - - if (!(acpi_dbg_level & ACPI_LV_NAMES) - || !(acpi_dbg_layer & ACPI_NAMESPACE)) { - return; - } - - /* Print the entire name */ - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "[")); - - while (num_segments) { - for (i = 0; i < 4; i++) { - ACPI_IS_PRINT(pathname[i]) ? - acpi_os_printf("%c", pathname[i]) : - acpi_os_printf("?"); - } - - pathname += ACPI_NAME_SIZE; - num_segments--; - if (num_segments) { - acpi_os_printf("."); - } - } - - acpi_os_printf("]\n"); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_dump_pathname - * - * PARAMETERS: Handle - Object - * Msg - Prefix message - * Level - Desired debug level - * Component - Caller's component ID - * - * RETURN: None - * - * DESCRIPTION: Print an object's full namespace pathname - * Manages allocation/freeing of a pathname buffer - * - ******************************************************************************/ - -void -acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component) -{ - - ACPI_FUNCTION_TRACE(ns_dump_pathname); - - /* Do this only if the requested debug level and component are enabled */ - - if (!(acpi_dbg_level & level) || !(acpi_dbg_layer & component)) { - return_VOID; - } - - /* Convert handle to a full pathname and print it (with supplied message) */ - - acpi_ns_print_node_pathname(handle, msg); - acpi_os_printf("\n"); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_dump_one_object - * - * PARAMETERS: obj_handle - Node to be dumped - * Level - Nesting level of the handle - * Context - Passed into walk_namespace - * return_value - Not used - * - * RETURN: Status - * - * DESCRIPTION: Dump a single Node - * This procedure is a user_function called by acpi_ns_walk_namespace. - * - ******************************************************************************/ - -acpi_status -acpi_ns_dump_one_object(acpi_handle obj_handle, - u32 level, void *context, void **return_value) -{ - struct acpi_walk_info *info = (struct acpi_walk_info *)context; - struct acpi_namespace_node *this_node; - union acpi_operand_object *obj_desc = NULL; - acpi_object_type obj_type; - acpi_object_type type; - u32 bytes_to_dump; - u32 dbg_level; - u32 i; - - ACPI_FUNCTION_NAME(ns_dump_one_object); - - /* Is output enabled? */ - - if (!(acpi_dbg_level & info->debug_level)) { - return (AE_OK); - } - - if (!obj_handle) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Null object handle\n")); - return (AE_OK); - } - - this_node = acpi_ns_map_handle_to_node(obj_handle); - type = this_node->type; - - /* Check if the owner matches */ - - if ((info->owner_id != ACPI_OWNER_ID_MAX) && - (info->owner_id != this_node->owner_id)) { - return (AE_OK); - } - - if (!(info->display_type & ACPI_DISPLAY_SHORT)) { - - /* Indent the object according to the level */ - - acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " "); - - /* Check the node type and name */ - - if (type > ACPI_TYPE_LOCAL_MAX) { - ACPI_WARNING((AE_INFO, "Invalid ACPI Object Type %08X", - type)); - } - - if (!acpi_ut_valid_acpi_name(this_node->name.integer)) { - this_node->name.integer = - acpi_ut_repair_name(this_node->name.ascii); - - ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X", - this_node->name.integer)); - } - - acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node)); - } - - /* - * Now we can print out the pertinent information - */ - acpi_os_printf(" %-12s %p %2.2X ", - acpi_ut_get_type_name(type), this_node, - this_node->owner_id); - - dbg_level = acpi_dbg_level; - acpi_dbg_level = 0; - obj_desc = acpi_ns_get_attached_object(this_node); - acpi_dbg_level = dbg_level; - - /* Temp nodes are those nodes created by a control method */ - - if (this_node->flags & ANOBJ_TEMPORARY) { - acpi_os_printf("(T) "); - } - - switch (info->display_type & ACPI_DISPLAY_MASK) { - case ACPI_DISPLAY_SUMMARY: - - if (!obj_desc) { - - /* No attached object, we are done */ - - acpi_os_printf("\n"); - return (AE_OK); - } - - switch (type) { - case ACPI_TYPE_PROCESSOR: - - acpi_os_printf("ID %X Len %.4X Addr %p\n", - obj_desc->processor.proc_id, - obj_desc->processor.length, - ACPI_CAST_PTR(void, - obj_desc->processor. - address)); - break; - - case ACPI_TYPE_DEVICE: - - acpi_os_printf("Notify Object: %p\n", obj_desc); - break; - - case ACPI_TYPE_METHOD: - - acpi_os_printf("Args %X Len %.4X Aml %p\n", - (u32) obj_desc->method.param_count, - obj_desc->method.aml_length, - obj_desc->method.aml_start); - break; - - case ACPI_TYPE_INTEGER: - - acpi_os_printf("= %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(obj_desc->integer. - value)); - break; - - case ACPI_TYPE_PACKAGE: - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - acpi_os_printf("Elements %.2X\n", - obj_desc->package.count); - } else { - acpi_os_printf("[Length not yet evaluated]\n"); - } - break; - - case ACPI_TYPE_BUFFER: - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - acpi_os_printf("Len %.2X", - obj_desc->buffer.length); - - /* Dump some of the buffer */ - - if (obj_desc->buffer.length > 0) { - acpi_os_printf(" ="); - for (i = 0; - (i < obj_desc->buffer.length - && i < 12); i++) { - acpi_os_printf(" %.2hX", - obj_desc->buffer. - pointer[i]); - } - } - acpi_os_printf("\n"); - } else { - acpi_os_printf("[Length not yet evaluated]\n"); - } - break; - - case ACPI_TYPE_STRING: - - acpi_os_printf("Len %.2X ", obj_desc->string.length); - acpi_ut_print_string(obj_desc->string.pointer, 32); - acpi_os_printf("\n"); - break; - - case ACPI_TYPE_REGION: - - acpi_os_printf("[%s]", - acpi_ut_get_region_name(obj_desc->region. - space_id)); - if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { - acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n", - ACPI_FORMAT_NATIVE_UINT - (obj_desc->region.address), - obj_desc->region.length); - } else { - acpi_os_printf - (" [Address/Length not yet evaluated]\n"); - } - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - - acpi_os_printf("[%s]\n", - acpi_ut_get_reference_name(obj_desc)); - break; - - case ACPI_TYPE_BUFFER_FIELD: - - if (obj_desc->buffer_field.buffer_obj && - obj_desc->buffer_field.buffer_obj->buffer.node) { - acpi_os_printf("Buf [%4.4s]", - acpi_ut_get_node_name(obj_desc-> - buffer_field. - buffer_obj-> - buffer. - node)); - } - break; - - case ACPI_TYPE_LOCAL_REGION_FIELD: - - acpi_os_printf("Rgn [%4.4s]", - acpi_ut_get_node_name(obj_desc-> - common_field. - region_obj->region. - node)); - break; - - case ACPI_TYPE_LOCAL_BANK_FIELD: - - acpi_os_printf("Rgn [%4.4s] Bnk [%4.4s]", - acpi_ut_get_node_name(obj_desc-> - common_field. - region_obj->region. - node), - acpi_ut_get_node_name(obj_desc-> - bank_field. - bank_obj-> - common_field. - node)); - break; - - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - acpi_os_printf("Idx [%4.4s] Dat [%4.4s]", - acpi_ut_get_node_name(obj_desc-> - index_field. - index_obj-> - common_field.node), - acpi_ut_get_node_name(obj_desc-> - index_field. - data_obj-> - common_field. - node)); - break; - - case ACPI_TYPE_LOCAL_ALIAS: - case ACPI_TYPE_LOCAL_METHOD_ALIAS: - - acpi_os_printf("Target %4.4s (%p)\n", - acpi_ut_get_node_name(obj_desc), - obj_desc); - break; - - default: - - acpi_os_printf("Object %p\n", obj_desc); - break; - } - - /* Common field handling */ - - switch (type) { - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - acpi_os_printf(" Off %.3X Len %.2X Acc %.2hd\n", - (obj_desc->common_field. - base_byte_offset * 8) - + - obj_desc->common_field. - start_field_bit_offset, - obj_desc->common_field.bit_length, - obj_desc->common_field. - access_byte_width); - break; - - default: - break; - } - break; - - case ACPI_DISPLAY_OBJECTS: - - acpi_os_printf("O:%p", obj_desc); - if (!obj_desc) { - - /* No attached object, we are done */ - - acpi_os_printf("\n"); - return (AE_OK); - } - - acpi_os_printf("(R%d)", obj_desc->common.reference_count); - - switch (type) { - case ACPI_TYPE_METHOD: - - /* Name is a Method and its AML offset/length are set */ - - acpi_os_printf(" M:%p-%X\n", obj_desc->method.aml_start, - obj_desc->method.aml_length); - break; - - case ACPI_TYPE_INTEGER: - - acpi_os_printf(" I:%8.8X8.8%X\n", - ACPI_FORMAT_UINT64(obj_desc->integer. - value)); - break; - - case ACPI_TYPE_STRING: - - acpi_os_printf(" S:%p-%X\n", obj_desc->string.pointer, - obj_desc->string.length); - break; - - case ACPI_TYPE_BUFFER: - - acpi_os_printf(" B:%p-%X\n", obj_desc->buffer.pointer, - obj_desc->buffer.length); - break; - - default: - - acpi_os_printf("\n"); - break; - } - break; - - default: - acpi_os_printf("\n"); - break; - } - - /* If debug turned off, done */ - - if (!(acpi_dbg_level & ACPI_LV_VALUES)) { - return (AE_OK); - } - - /* If there is an attached object, display it */ - - dbg_level = acpi_dbg_level; - acpi_dbg_level = 0; - obj_desc = acpi_ns_get_attached_object(this_node); - acpi_dbg_level = dbg_level; - - /* Dump attached objects */ - - while (obj_desc) { - obj_type = ACPI_TYPE_INVALID; - acpi_os_printf("Attached Object %p: ", obj_desc); - - /* Decode the type of attached object and dump the contents */ - - switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { - case ACPI_DESC_TYPE_NAMED: - - acpi_os_printf("(Ptr to Node)\n"); - bytes_to_dump = sizeof(struct acpi_namespace_node); - ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump); - break; - - case ACPI_DESC_TYPE_OPERAND: - - obj_type = ACPI_GET_OBJECT_TYPE(obj_desc); - - if (obj_type > ACPI_TYPE_LOCAL_MAX) { - acpi_os_printf - ("(Pointer to ACPI Object type %.2X [UNKNOWN])\n", - obj_type); - bytes_to_dump = 32; - } else { - acpi_os_printf - ("(Pointer to ACPI Object type %.2X [%s])\n", - obj_type, acpi_ut_get_type_name(obj_type)); - bytes_to_dump = - sizeof(union acpi_operand_object); - } - - ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump); - break; - - default: - - break; - } - - /* If value is NOT an internal object, we are done */ - - if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != - ACPI_DESC_TYPE_OPERAND) { - goto cleanup; - } - - /* - * Valid object, get the pointer to next level, if any - */ - switch (obj_type) { - case ACPI_TYPE_BUFFER: - case ACPI_TYPE_STRING: - /* - * NOTE: takes advantage of common fields between string/buffer - */ - bytes_to_dump = obj_desc->string.length; - obj_desc = (void *)obj_desc->string.pointer; - acpi_os_printf("(Buffer/String pointer %p length %X)\n", - obj_desc, bytes_to_dump); - ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump); - goto cleanup; - - case ACPI_TYPE_BUFFER_FIELD: - obj_desc = - (union acpi_operand_object *)obj_desc->buffer_field. - buffer_obj; - break; - - case ACPI_TYPE_PACKAGE: - obj_desc = (void *)obj_desc->package.elements; - break; - - case ACPI_TYPE_METHOD: - obj_desc = (void *)obj_desc->method.aml_start; - break; - - case ACPI_TYPE_LOCAL_REGION_FIELD: - obj_desc = (void *)obj_desc->field.region_obj; - break; - - case ACPI_TYPE_LOCAL_BANK_FIELD: - obj_desc = (void *)obj_desc->bank_field.region_obj; - break; - - case ACPI_TYPE_LOCAL_INDEX_FIELD: - obj_desc = (void *)obj_desc->index_field.index_obj; - break; - - default: - goto cleanup; - } - - obj_type = ACPI_TYPE_INVALID; /* Terminate loop after next pass */ - } - - cleanup: - acpi_os_printf("\n"); - return (AE_OK); -} - -#ifdef ACPI_FUTURE_USAGE -/******************************************************************************* - * - * FUNCTION: acpi_ns_dump_objects - * - * PARAMETERS: Type - Object type to be dumped - * display_type - 0 or ACPI_DISPLAY_SUMMARY - * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX - * for an effectively unlimited depth. - * owner_id - Dump only objects owned by this ID. Use - * ACPI_UINT32_MAX to match all owners. - * start_handle - Where in namespace to start/end search - * - * RETURN: None - * - * DESCRIPTION: Dump typed objects within the loaded namespace. - * Uses acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object. - * - ******************************************************************************/ - -void -acpi_ns_dump_objects(acpi_object_type type, - u8 display_type, - u32 max_depth, - acpi_owner_id owner_id, acpi_handle start_handle) -{ - struct acpi_walk_info info; - - ACPI_FUNCTION_ENTRY(); - - info.debug_level = ACPI_LV_TABLES; - info.owner_id = owner_id; - info.display_type = display_type; - - (void)acpi_ns_walk_namespace(type, start_handle, max_depth, - ACPI_NS_WALK_NO_UNLOCK | - ACPI_NS_WALK_TEMP_NODES, - acpi_ns_dump_one_object, (void *)&info, - NULL); -} -#endif /* ACPI_FUTURE_USAGE */ - -/******************************************************************************* - * - * FUNCTION: acpi_ns_dump_entry - * - * PARAMETERS: Handle - Node to be dumped - * debug_level - Output level - * - * RETURN: None - * - * DESCRIPTION: Dump a single Node - * - ******************************************************************************/ - -void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level) -{ - struct acpi_walk_info info; - - ACPI_FUNCTION_ENTRY(); - - info.debug_level = debug_level; - info.owner_id = ACPI_OWNER_ID_MAX; - info.display_type = ACPI_DISPLAY_SUMMARY; - - (void)acpi_ns_dump_one_object(handle, 1, &info, NULL); -} - -#ifdef ACPI_ASL_COMPILER -/******************************************************************************* - * - * FUNCTION: acpi_ns_dump_tables - * - * PARAMETERS: search_base - Root of subtree to be dumped, or - * NS_ALL to dump the entire namespace - * max_depth - Maximum depth of dump. Use INT_MAX - * for an effectively unlimited depth. - * - * RETURN: None - * - * DESCRIPTION: Dump the name space, or a portion of it. - * - ******************************************************************************/ - -void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth) -{ - acpi_handle search_handle = search_base; - - ACPI_FUNCTION_TRACE(ns_dump_tables); - - if (!acpi_gbl_root_node) { - /* - * If the name space has not been initialized, - * there is nothing to dump. - */ - ACPI_DEBUG_PRINT((ACPI_DB_TABLES, - "namespace not initialized!\n")); - return_VOID; - } - - if (ACPI_NS_ALL == search_base) { - - /* Entire namespace */ - - search_handle = acpi_gbl_root_node; - ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "\\\n")); - } - - acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, max_depth, - ACPI_OWNER_ID_MAX, search_handle); - return_VOID; -} -#endif /* _ACPI_ASL_COMPILER */ -#endif /* defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) */ diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c deleted file mode 100644 index cc3df78258ed..000000000000 --- a/drivers/acpi/namespace/nsdumpdv.c +++ /dev/null @@ -1,141 +0,0 @@ -/****************************************************************************** - * - * Module Name: nsdump - table dumping routines for debug - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include - -/* TBD: This entire module is apparently obsolete and should be removed */ - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsdumpdv") -#ifdef ACPI_OBSOLETE_FUNCTIONS -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) -#include -/******************************************************************************* - * - * FUNCTION: acpi_ns_dump_one_device - * - * PARAMETERS: Handle - Node to be dumped - * Level - Nesting level of the handle - * Context - Passed into walk_namespace - * return_value - Not used - * - * RETURN: Status - * - * DESCRIPTION: Dump a single Node that represents a device - * This procedure is a user_function called by acpi_ns_walk_namespace. - * - ******************************************************************************/ -static acpi_status -acpi_ns_dump_one_device(acpi_handle obj_handle, - u32 level, void *context, void **return_value) -{ - struct acpi_buffer buffer; - struct acpi_device_info *info; - acpi_status status; - u32 i; - - ACPI_FUNCTION_NAME(ns_dump_one_device); - - status = - acpi_ns_dump_one_object(obj_handle, level, context, return_value); - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_get_object_info(obj_handle, &buffer); - if (ACPI_SUCCESS(status)) { - info = buffer.pointer; - for (i = 0; i < level; i++) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " ")); - } - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, - " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", - info->hardware_id.value, - ACPI_FORMAT_UINT64(info->address), - info->current_status)); - ACPI_FREE(info); - } - - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_dump_root_devices - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Dump all objects of type "device" - * - ******************************************************************************/ - -void acpi_ns_dump_root_devices(void) -{ - acpi_handle sys_bus_handle; - acpi_status status; - - ACPI_FUNCTION_NAME(ns_dump_root_devices); - - /* Only dump the table if tracing is enabled */ - - if (!(ACPI_LV_TABLES & acpi_dbg_level)) { - return; - } - - status = acpi_get_handle(NULL, ACPI_NS_SYSTEM_BUS, &sys_bus_handle); - if (ACPI_FAILURE(status)) { - return; - } - - ACPI_DEBUG_PRINT((ACPI_DB_TABLES, - "Display of all devices in the namespace:\n")); - - status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, sys_bus_handle, - ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, - acpi_ns_dump_one_device, NULL, NULL); -} - -#endif -#endif diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c deleted file mode 100644 index a8d7764c73b7..000000000000 --- a/drivers/acpi/namespace/nseval.c +++ /dev/null @@ -1,278 +0,0 @@ -/******************************************************************************* - * - * Module Name: nseval - Object evaluation, includes control method execution - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nseval") - -/******************************************************************************* - * - * FUNCTION: acpi_ns_evaluate - * - * PARAMETERS: Info - Evaluation info block, contains: - * prefix_node - Prefix or Method/Object Node to execute - * Pathname - Name of method to execute, If NULL, the - * Node is the object to execute - * Parameters - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * parameter_type - Type of Parameter list - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * Flags - ACPI_IGNORE_RETURN_VALUE to delete return - * - * RETURN: Status - * - * DESCRIPTION: Execute a control method or return the current value of an - * ACPI namespace object. - * - * MUTEX: Locks interpreter - * - ******************************************************************************/ -acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) -{ - acpi_status status; - struct acpi_namespace_node *node; - - ACPI_FUNCTION_TRACE(ns_evaluate); - - if (!info) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Initialize the return value to an invalid object */ - - info->return_object = NULL; - info->param_count = 0; - - /* - * Get the actual namespace node for the target object. Handles these cases: - * - * 1) Null node, Pathname (absolute path) - * 2) Node, Pathname (path relative to Node) - * 3) Node, Null Pathname - */ - status = acpi_ns_get_node(info->prefix_node, info->pathname, - ACPI_NS_NO_UPSEARCH, &info->resolved_node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * For a method alias, we must grab the actual method node so that proper - * scoping context will be established before execution. - */ - if (acpi_ns_get_type(info->resolved_node) == - ACPI_TYPE_LOCAL_METHOD_ALIAS) { - info->resolved_node = - ACPI_CAST_PTR(struct acpi_namespace_node, - info->resolved_node->object); - } - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname, - info->resolved_node, - acpi_ns_get_attached_object(info->resolved_node))); - - node = info->resolved_node; - - /* - * Two major cases here: - * - * 1) The object is a control method -- execute it - * 2) The object is not a method -- just return it's current value - */ - if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) { - /* - * 1) Object is a control method - execute it - */ - - /* Verify that there is a method object associated with this node */ - - info->obj_desc = - acpi_ns_get_attached_object(info->resolved_node); - if (!info->obj_desc) { - ACPI_ERROR((AE_INFO, - "Control method has no attached sub-object")); - return_ACPI_STATUS(AE_NULL_OBJECT); - } - - /* Count the number of arguments being passed to the method */ - - if (info->parameters) { - while (info->parameters[info->param_count]) { - if (info->param_count > ACPI_METHOD_MAX_ARG) { - return_ACPI_STATUS(AE_LIMIT); - } - info->param_count++; - } - } - - - ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:", - ACPI_LV_INFO, _COMPONENT); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Method at AML address %p Length %X\n", - info->obj_desc->method.aml_start + 1, - info->obj_desc->method.aml_length - 1)); - - /* - * Any namespace deletion must acquire both the namespace and - * interpreter locks to ensure that no thread is using the portion of - * the namespace that is being deleted. - * - * Execute the method via the interpreter. The interpreter is locked - * here before calling into the AML parser - */ - acpi_ex_enter_interpreter(); - status = acpi_ps_execute_method(info); - acpi_ex_exit_interpreter(); - } else { - /* - * 2) Object is not a method, return its current value - * - * Disallow certain object types. For these, "evaluation" is undefined. - */ - switch (info->resolved_node->type) { - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_EVENT: - case ACPI_TYPE_MUTEX: - case ACPI_TYPE_REGION: - case ACPI_TYPE_THERMAL: - case ACPI_TYPE_LOCAL_SCOPE: - - ACPI_ERROR((AE_INFO, - "[%4.4s] Evaluation of object type [%s] is not supported", - info->resolved_node->name.ascii, - acpi_ut_get_type_name(info->resolved_node-> - type))); - - return_ACPI_STATUS(AE_TYPE); - - default: - break; - } - - /* - * Objects require additional resolution steps (e.g., the Node may be - * a field that must be read, etc.) -- we can't just grab the object - * out of the node. - * - * Use resolve_node_to_value() to get the associated value. - * - * NOTE: we can get away with passing in NULL for a walk state because - * resolved_node is guaranteed to not be a reference to either a method - * local or a method argument (because this interface is never called - * from a running method.) - * - * Even though we do not directly invoke the interpreter for object - * resolution, we must lock it because we could access an opregion. - * The opregion access code assumes that the interpreter is locked. - */ - acpi_ex_enter_interpreter(); - - /* Function has a strange interface */ - - status = - acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); - acpi_ex_exit_interpreter(); - - /* - * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed - * in resolved_node. - */ - if (ACPI_SUCCESS(status)) { - status = AE_CTRL_RETURN_VALUE; - info->return_object = - ACPI_CAST_PTR(union acpi_operand_object, - info->resolved_node); - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Returning object %p [%s]\n", - info->return_object, - acpi_ut_get_object_type_name(info-> - return_object))); - } - } - - /* - * Check input argument count against the ASL-defined count for a method. - * Also check predefined names: argument count and return value against - * the ACPI specification. Some incorrect return value types are repaired. - */ - (void)acpi_ns_check_predefined_names(node, info->param_count, - status, &info->return_object); - - /* Check if there is a return value that must be dealt with */ - - if (status == AE_CTRL_RETURN_VALUE) { - - /* If caller does not want the return value, delete it */ - - if (info->flags & ACPI_IGNORE_RETURN_VALUE) { - acpi_ut_remove_reference(info->return_object); - info->return_object = NULL; - } - - /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ - - status = AE_OK; - } - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "*** Completed evaluation of object %s ***\n", - info->pathname)); - - /* - * Namespace was unlocked by the handling acpi_ns* function, so we - * just return - */ - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c deleted file mode 100644 index fe470c4b38f7..000000000000 --- a/drivers/acpi/namespace/nsinit.c +++ /dev/null @@ -1,593 +0,0 @@ -/****************************************************************************** - * - * Module Name: nsinit - namespace initialization - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsinit") - -/* Local prototypes */ -static acpi_status -acpi_ns_init_one_object(acpi_handle obj_handle, - u32 level, void *context, void **return_value); - -static acpi_status -acpi_ns_init_one_device(acpi_handle obj_handle, - u32 nesting_level, void *context, void **return_value); - -static acpi_status -acpi_ns_find_ini_methods(acpi_handle obj_handle, - u32 nesting_level, void *context, void **return_value); - -/******************************************************************************* - * - * FUNCTION: acpi_ns_initialize_objects - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Walk the entire namespace and perform any necessary - * initialization on the objects found therein - * - ******************************************************************************/ - -acpi_status acpi_ns_initialize_objects(void) -{ - acpi_status status; - struct acpi_init_walk_info info; - - ACPI_FUNCTION_TRACE(ns_initialize_objects); - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "**** Starting initialization of namespace objects ****\n")); - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "Completing Region/Field/Buffer/Package initialization:")); - - /* Set all init info to zero */ - - ACPI_MEMSET(&info, 0, sizeof(struct acpi_init_walk_info)); - - /* Walk entire namespace from the supplied root */ - - status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, acpi_ns_init_one_object, - &info, NULL); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); - } - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd Buffers %hd/%hd Packages (%hd nodes)\n", - info.op_region_init, info.op_region_count, - info.field_init, info.field_count, - info.buffer_init, info.buffer_count, - info.package_init, info.package_count, - info.object_count)); - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "%hd Control Methods found\n", info.method_count)); - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "%hd Op Regions found\n", info.op_region_count)); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_initialize_devices - * - * PARAMETERS: None - * - * RETURN: acpi_status - * - * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices. - * This means running _INI on all present devices. - * - * Note: We install PCI config space handler on region access, - * not here. - * - ******************************************************************************/ - -acpi_status acpi_ns_initialize_devices(void) -{ - acpi_status status; - struct acpi_device_walk_info info; - - ACPI_FUNCTION_TRACE(ns_initialize_devices); - - /* Init counters */ - - info.device_count = 0; - info.num_STA = 0; - info.num_INI = 0; - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "Initializing Device/Processor/Thermal objects by executing _INI methods:")); - - /* Tree analysis: find all subtrees that contain _INI methods */ - - status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, FALSE, - acpi_ns_find_ini_methods, &info, NULL); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - - /* Allocate the evaluation information block */ - - info.evaluate_info = - ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); - if (!info.evaluate_info) { - status = AE_NO_MEMORY; - goto error_exit; - } - - /* Walk namespace to execute all _INIs on present devices */ - - status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, FALSE, - acpi_ns_init_one_device, &info, NULL); - - ACPI_FREE(info.evaluate_info); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nExecuted %hd _INI methods requiring %hd _STA executions (examined %hd objects)\n", - info.num_INI, info.num_STA, info.device_count)); - - return_ACPI_STATUS(status); - - error_exit: - ACPI_EXCEPTION((AE_INFO, status, "During device initialization")); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_init_one_object - * - * PARAMETERS: obj_handle - Node - * Level - Current nesting level - * Context - Points to a init info struct - * return_value - Not used - * - * RETURN: Status - * - * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object - * within the namespace. - * - * Currently, the only objects that require initialization are: - * 1) Methods - * 2) Op Regions - * - ******************************************************************************/ - -static acpi_status -acpi_ns_init_one_object(acpi_handle obj_handle, - u32 level, void *context, void **return_value) -{ - acpi_object_type type; - acpi_status status = AE_OK; - struct acpi_init_walk_info *info = - (struct acpi_init_walk_info *)context; - struct acpi_namespace_node *node = - (struct acpi_namespace_node *)obj_handle; - union acpi_operand_object *obj_desc; - - ACPI_FUNCTION_NAME(ns_init_one_object); - - info->object_count++; - - /* And even then, we are only interested in a few object types */ - - type = acpi_ns_get_type(obj_handle); - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - return (AE_OK); - } - - /* Increment counters for object types we are looking for */ - - switch (type) { - case ACPI_TYPE_REGION: - info->op_region_count++; - break; - - case ACPI_TYPE_BUFFER_FIELD: - info->field_count++; - break; - - case ACPI_TYPE_LOCAL_BANK_FIELD: - info->field_count++; - break; - - case ACPI_TYPE_BUFFER: - info->buffer_count++; - break; - - case ACPI_TYPE_PACKAGE: - info->package_count++; - break; - - default: - - /* No init required, just exit now */ - return (AE_OK); - } - - /* - * If the object is already initialized, nothing else to do - */ - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return (AE_OK); - } - - /* - * Must lock the interpreter before executing AML code - */ - acpi_ex_enter_interpreter(); - - /* - * Each of these types can contain executable AML code within the - * declaration. - */ - switch (type) { - case ACPI_TYPE_REGION: - - info->op_region_init++; - status = acpi_ds_get_region_arguments(obj_desc); - break; - - case ACPI_TYPE_BUFFER_FIELD: - - info->field_init++; - status = acpi_ds_get_buffer_field_arguments(obj_desc); - break; - - case ACPI_TYPE_LOCAL_BANK_FIELD: - - info->field_init++; - status = acpi_ds_get_bank_field_arguments(obj_desc); - break; - - case ACPI_TYPE_BUFFER: - - info->buffer_init++; - status = acpi_ds_get_buffer_arguments(obj_desc); - break; - - case ACPI_TYPE_PACKAGE: - - info->package_init++; - status = acpi_ds_get_package_arguments(obj_desc); - break; - - default: - /* No other types can get here */ - break; - } - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not execute arguments for [%4.4s] (%s)", - acpi_ut_get_node_name(node), - acpi_ut_get_type_name(type))); - } - - /* - * Print a dot for each object unless we are going to print the entire - * pathname - */ - if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); - } - - /* - * We ignore errors from above, and always return OK, since we don't want - * to abort the walk on any single error. - */ - acpi_ex_exit_interpreter(); - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_find_ini_methods - * - * PARAMETERS: acpi_walk_callback - * - * RETURN: acpi_status - * - * DESCRIPTION: Called during namespace walk. Finds objects named _INI under - * device/processor/thermal objects, and marks the entire subtree - * with a SUBTREE_HAS_INI flag. This flag is used during the - * subsequent device initialization walk to avoid entire subtrees - * that do not contain an _INI. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_find_ini_methods(acpi_handle obj_handle, - u32 nesting_level, void *context, void **return_value) -{ - struct acpi_device_walk_info *info = - ACPI_CAST_PTR(struct acpi_device_walk_info, context); - struct acpi_namespace_node *node; - struct acpi_namespace_node *parent_node; - - /* Keep count of device/processor/thermal objects */ - - node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); - if ((node->type == ACPI_TYPE_DEVICE) || - (node->type == ACPI_TYPE_PROCESSOR) || - (node->type == ACPI_TYPE_THERMAL)) { - info->device_count++; - return (AE_OK); - } - - /* We are only looking for methods named _INI */ - - if (!ACPI_COMPARE_NAME(node->name.ascii, METHOD_NAME__INI)) { - return (AE_OK); - } - - /* - * The only _INI methods that we care about are those that are - * present under Device, Processor, and Thermal objects. - */ - parent_node = acpi_ns_get_parent_node(node); - switch (parent_node->type) { - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_THERMAL: - - /* Mark parent and bubble up the INI present flag to the root */ - - while (parent_node) { - parent_node->flags |= ANOBJ_SUBTREE_HAS_INI; - parent_node = acpi_ns_get_parent_node(parent_node); - } - break; - - default: - break; - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_init_one_device - * - * PARAMETERS: acpi_walk_callback - * - * RETURN: acpi_status - * - * DESCRIPTION: This is called once per device soon after ACPI is enabled - * to initialize each device. It determines if the device is - * present, and if so, calls _INI. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_init_one_device(acpi_handle obj_handle, - u32 nesting_level, void *context, void **return_value) -{ - struct acpi_device_walk_info *walk_info = - ACPI_CAST_PTR(struct acpi_device_walk_info, context); - struct acpi_evaluate_info *info = walk_info->evaluate_info; - u32 flags; - acpi_status status; - struct acpi_namespace_node *device_node; - - ACPI_FUNCTION_TRACE(ns_init_one_device); - - /* We are interested in Devices, Processors and thermal_zones only */ - - device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); - if ((device_node->type != ACPI_TYPE_DEVICE) && - (device_node->type != ACPI_TYPE_PROCESSOR) && - (device_node->type != ACPI_TYPE_THERMAL)) { - return_ACPI_STATUS(AE_OK); - } - - /* - * Because of an earlier namespace analysis, all subtrees that contain an - * _INI method are tagged. - * - * If this device subtree does not contain any _INI methods, we - * can exit now and stop traversing this entire subtree. - */ - if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) { - return_ACPI_STATUS(AE_CTRL_DEPTH); - } - - /* - * Run _STA to determine if this device is present and functioning. We - * must know this information for two important reasons (from ACPI spec): - * - * 1) We can only run _INI if the device is present. - * 2) We must abort the device tree walk on this subtree if the device is - * not present and is not functional (we will not examine the children) - * - * The _STA method is not required to be present under the device, we - * assume the device is present if _STA does not exist. - */ - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA)); - - status = acpi_ut_execute_STA(device_node, &flags); - if (ACPI_FAILURE(status)) { - - /* Ignore error and move on to next device */ - - return_ACPI_STATUS(AE_OK); - } - - /* - * Flags == -1 means that _STA was not found. In this case, we assume that - * the device is both present and functional. - * - * From the ACPI spec, description of _STA: - * - * "If a device object (including the processor object) does not have an - * _STA object, then OSPM assumes that all of the above bits are set (in - * other words, the device is present, ..., and functioning)" - */ - if (flags != ACPI_UINT32_MAX) { - walk_info->num_STA++; - } - - /* - * Examine the PRESENT and FUNCTIONING status bits - * - * Note: ACPI spec does not seem to specify behavior for the present but - * not functioning case, so we assume functioning if present. - */ - if (!(flags & ACPI_STA_DEVICE_PRESENT)) { - - /* Device is not present, we must examine the Functioning bit */ - - if (flags & ACPI_STA_DEVICE_FUNCTIONING) { - /* - * Device is not present but is "functioning". In this case, - * we will not run _INI, but we continue to examine the children - * of this device. - * - * From the ACPI spec, description of _STA: (Note - no mention - * of whether to run _INI or not on the device in question) - * - * "_STA may return bit 0 clear (not present) with bit 3 set - * (device is functional). This case is used to indicate a valid - * device for which no device driver should be loaded (for example, - * a bridge device.) Children of this device may be present and - * valid. OSPM should continue enumeration below a device whose - * _STA returns this bit combination" - */ - return_ACPI_STATUS(AE_OK); - } else { - /* - * Device is not present and is not functioning. We must abort the - * walk of this subtree immediately -- don't look at the children - * of such a device. - * - * From the ACPI spec, description of _INI: - * - * "If the _STA method indicates that the device is not present, - * OSPM will not run the _INI and will not examine the children - * of the device for _INI methods" - */ - return_ACPI_STATUS(AE_CTRL_DEPTH); - } - } - - /* - * The device is present or is assumed present if no _STA exists. - * Run the _INI if it exists (not required to exist) - * - * Note: We know there is an _INI within this subtree, but it may not be - * under this particular device, it may be lower in the branch. - */ - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI)); - - info->prefix_node = device_node; - info->pathname = METHOD_NAME__INI; - info->parameters = NULL; - info->flags = ACPI_IGNORE_RETURN_VALUE; - - /* - * Some hardware relies on this being executed as atomically - * as possible (without an NMI being received in the middle of - * this) - so disable NMIs and initialize the device: - */ - acpi_nmi_disable(); - status = acpi_ns_evaluate(info); - acpi_nmi_enable(); - - if (ACPI_SUCCESS(status)) { - walk_info->num_INI++; - - if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && - (!(acpi_dbg_level & ACPI_LV_INFO))) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); - } - } -#ifdef ACPI_DEBUG_OUTPUT - else if (status != AE_NOT_FOUND) { - - /* Ignore error and move on to next device */ - - char *scope_name = - acpi_ns_get_external_pathname(info->resolved_node); - - ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution", - scope_name)); - ACPI_FREE(scope_name); - } -#endif - - /* Ignore errors from above */ - - status = AE_OK; - - /* - * The _INI method has been run if present; call the Global Initialization - * Handler for this device. - */ - if (acpi_gbl_init_handler) { - status = - acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI); - } - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c deleted file mode 100644 index a6e92b31a06f..000000000000 --- a/drivers/acpi/namespace/nsload.c +++ /dev/null @@ -1,315 +0,0 @@ -/****************************************************************************** - * - * Module Name: nsload - namespace loading/expanding/contracting procedures - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsload") - -/* Local prototypes */ -#ifdef ACPI_FUTURE_IMPLEMENTATION -acpi_status acpi_ns_unload_namespace(acpi_handle handle); - -static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle); -#endif - -#ifndef ACPI_NO_METHOD_EXECUTION -/******************************************************************************* - * - * FUNCTION: acpi_ns_load_table - * - * PARAMETERS: table_index - Index for table to be loaded - * Node - Owning NS node - * - * RETURN: Status - * - * DESCRIPTION: Load one ACPI table into the namespace - * - ******************************************************************************/ - -acpi_status -acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ns_load_table); - - /* - * Parse the table and load the namespace with all named - * objects found within. Control methods are NOT parsed - * at this time. In fact, the control methods cannot be - * parsed until the entire namespace is loaded, because - * if a control method makes a forward reference (call) - * to another control method, we can't continue parsing - * because we don't know how many arguments to parse next! - */ - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* If table already loaded into namespace, just return */ - - if (acpi_tb_is_table_loaded(table_index)) { - status = AE_ALREADY_EXISTS; - goto unlock; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "**** Loading table into namespace ****\n")); - - status = acpi_tb_allocate_owner_id(table_index); - if (ACPI_FAILURE(status)) { - goto unlock; - } - - status = acpi_ns_parse_table(table_index, node); - if (ACPI_SUCCESS(status)) { - acpi_tb_set_table_loaded_flag(table_index, TRUE); - } else { - (void)acpi_tb_release_owner_id(table_index); - } - - unlock: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Now we can parse the control methods. We always parse - * them here for a sanity check, and if configured for - * just-in-time parsing, we delete the control method - * parse trees. - */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "**** Begin Table Method Parsing and Object Initialization ****\n")); - - status = acpi_ds_initialize_objects(table_index, node); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "**** Completed Table Method Parsing and Object Initialization ****\n")); - - return_ACPI_STATUS(status); -} - -#ifdef ACPI_OBSOLETE_FUNCTIONS -/******************************************************************************* - * - * FUNCTION: acpi_load_namespace - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. - * (DSDT points to either the BIOS or a buffer.) - * - ******************************************************************************/ - -acpi_status acpi_ns_load_namespace(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_load_name_space); - - /* There must be at least a DSDT installed */ - - if (acpi_gbl_DSDT == NULL) { - ACPI_ERROR((AE_INFO, "DSDT is not in memory")); - return_ACPI_STATUS(AE_NO_ACPI_TABLES); - } - - /* - * Load the namespace. The DSDT is required, - * but the SSDT and PSDT tables are optional. - */ - status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Ignore exceptions from these */ - - (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT); - (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT); - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "ACPI Namespace successfully loaded at root %p\n", - acpi_gbl_root_node)); - - return_ACPI_STATUS(status); -} -#endif - -#ifdef ACPI_FUTURE_IMPLEMENTATION -/******************************************************************************* - * - * FUNCTION: acpi_ns_delete_subtree - * - * PARAMETERS: start_handle - Handle in namespace where search begins - * - * RETURNS Status - * - * DESCRIPTION: Walks the namespace starting at the given handle and deletes - * all objects, entries, and scopes in the entire subtree. - * - * Namespace/Interpreter should be locked or the subsystem should - * be in shutdown before this routine is called. - * - ******************************************************************************/ - -static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) -{ - acpi_status status; - acpi_handle child_handle; - acpi_handle parent_handle; - acpi_handle next_child_handle; - acpi_handle dummy; - u32 level; - - ACPI_FUNCTION_TRACE(ns_delete_subtree); - - parent_handle = start_handle; - child_handle = NULL; - level = 1; - - /* - * Traverse the tree of objects until we bubble back up - * to where we started. - */ - while (level > 0) { - - /* Attempt to get the next object in this scope */ - - status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, - child_handle, &next_child_handle); - - child_handle = next_child_handle; - - /* Did we get a new object? */ - - if (ACPI_SUCCESS(status)) { - - /* Check if this object has any children */ - - if (ACPI_SUCCESS - (acpi_get_next_object - (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) { - /* - * There is at least one child of this object, - * visit the object - */ - level++; - parent_handle = child_handle; - child_handle = NULL; - } - } else { - /* - * No more children in this object, go back up to - * the object's parent - */ - level--; - - /* Delete all children now */ - - acpi_ns_delete_children(child_handle); - - child_handle = parent_handle; - status = acpi_get_parent(parent_handle, &parent_handle); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - } - - /* Now delete the starting object, and we are done */ - - acpi_ns_delete_node(child_handle); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_unload_name_space - * - * PARAMETERS: Handle - Root of namespace subtree to be deleted - * - * RETURN: Status - * - * DESCRIPTION: Shrinks the namespace, typically in response to an undocking - * event. Deletes an entire subtree starting from (and - * including) the given handle. - * - ******************************************************************************/ - -acpi_status acpi_ns_unload_namespace(acpi_handle handle) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ns_unload_name_space); - - /* Parameter validation */ - - if (!acpi_gbl_root_node) { - return_ACPI_STATUS(AE_NO_NAMESPACE); - } - - if (!handle) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* This function does the real work */ - - status = acpi_ns_delete_subtree(handle); - - return_ACPI_STATUS(status); -} -#endif -#endif diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c deleted file mode 100644 index b7e301848ba7..000000000000 --- a/drivers/acpi/namespace/nsnames.c +++ /dev/null @@ -1,265 +0,0 @@ -/******************************************************************************* - * - * Module Name: nsnames - Name manipulation and search - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsnames") - -/******************************************************************************* - * - * FUNCTION: acpi_ns_build_external_path - * - * PARAMETERS: Node - NS node whose pathname is needed - * Size - Size of the pathname - * *name_buffer - Where to return the pathname - * - * RETURN: Status - * Places the pathname into the name_buffer, in external format - * (name segments separated by path separators) - * - * DESCRIPTION: Generate a full pathaname - * - ******************************************************************************/ -acpi_status -acpi_ns_build_external_path(struct acpi_namespace_node *node, - acpi_size size, char *name_buffer) -{ - acpi_size index; - struct acpi_namespace_node *parent_node; - - ACPI_FUNCTION_ENTRY(); - - /* Special case for root */ - - index = size - 1; - if (index < ACPI_NAME_SIZE) { - name_buffer[0] = AML_ROOT_PREFIX; - name_buffer[1] = 0; - return (AE_OK); - } - - /* Store terminator byte, then build name backwards */ - - parent_node = node; - name_buffer[index] = 0; - - while ((index > ACPI_NAME_SIZE) && (parent_node != acpi_gbl_root_node)) { - index -= ACPI_NAME_SIZE; - - /* Put the name into the buffer */ - - ACPI_MOVE_32_TO_32((name_buffer + index), &parent_node->name); - parent_node = acpi_ns_get_parent_node(parent_node); - - /* Prefix name with the path separator */ - - index--; - name_buffer[index] = ACPI_PATH_SEPARATOR; - } - - /* Overwrite final separator with the root prefix character */ - - name_buffer[index] = AML_ROOT_PREFIX; - - if (index != 0) { - ACPI_ERROR((AE_INFO, - "Could not construct external pathname; index=%X, size=%X, Path=%s", - (u32) index, (u32) size, &name_buffer[size])); - - return (AE_BAD_PARAMETER); - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_external_pathname - * - * PARAMETERS: Node - Namespace node whose pathname is needed - * - * RETURN: Pointer to storage containing the fully qualified name of - * the node, In external format (name segments separated by path - * separators.) - * - * DESCRIPTION: Used for debug printing in acpi_ns_search_table(). - * - ******************************************************************************/ - -char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) -{ - acpi_status status; - char *name_buffer; - acpi_size size; - - ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node); - - /* Calculate required buffer size based on depth below root */ - - size = acpi_ns_get_pathname_length(node); - if (!size) { - return_PTR(NULL); - } - - /* Allocate a buffer to be returned to caller */ - - name_buffer = ACPI_ALLOCATE_ZEROED(size); - if (!name_buffer) { - ACPI_ERROR((AE_INFO, "Allocation failure")); - return_PTR(NULL); - } - - /* Build the path in the allocated buffer */ - - status = acpi_ns_build_external_path(node, size, name_buffer); - if (ACPI_FAILURE(status)) { - ACPI_FREE(name_buffer); - return_PTR(NULL); - } - - return_PTR(name_buffer); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_pathname_length - * - * PARAMETERS: Node - Namespace node - * - * RETURN: Length of path, including prefix - * - * DESCRIPTION: Get the length of the pathname string for this node - * - ******************************************************************************/ - -acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) -{ - acpi_size size; - struct acpi_namespace_node *next_node; - - ACPI_FUNCTION_ENTRY(); - - /* - * Compute length of pathname as 5 * number of name segments. - * Go back up the parent tree to the root - */ - size = 0; - next_node = node; - - while (next_node && (next_node != acpi_gbl_root_node)) { - if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) { - ACPI_ERROR((AE_INFO, - "Invalid Namespace Node (%p) while traversing namespace", - next_node)); - return 0; - } - size += ACPI_PATH_SEGMENT_LENGTH; - next_node = acpi_ns_get_parent_node(next_node); - } - - if (!size) { - size = 1; /* Root node case */ - } - - return (size + 1); /* +1 for null string terminator */ -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_handle_to_pathname - * - * PARAMETERS: target_handle - Handle of named object whose name is - * to be found - * Buffer - Where the pathname is returned - * - * RETURN: Status, Buffer is filled with pathname if status is AE_OK - * - * DESCRIPTION: Build and return a full namespace pathname - * - ******************************************************************************/ - -acpi_status -acpi_ns_handle_to_pathname(acpi_handle target_handle, - struct acpi_buffer * buffer) -{ - acpi_status status; - struct acpi_namespace_node *node; - acpi_size required_size; - - ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle); - - node = acpi_ns_map_handle_to_node(target_handle); - if (!node) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Determine size required for the caller buffer */ - - required_size = acpi_ns_get_pathname_length(node); - if (!required_size) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Validate/Allocate/Clear caller buffer */ - - status = acpi_ut_initialize_buffer(buffer, required_size); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Build the path in the caller buffer */ - - status = - acpi_ns_build_external_path(node, required_size, buffer->pointer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n", - (char *)buffer->pointer, (u32) required_size)); - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c deleted file mode 100644 index ca9edeea27df..000000000000 --- a/drivers/acpi/namespace/nsobject.c +++ /dev/null @@ -1,441 +0,0 @@ -/******************************************************************************* - * - * Module Name: nsobject - Utilities for objects attached to namespace - * table entries - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsobject") - -/******************************************************************************* - * - * FUNCTION: acpi_ns_attach_object - * - * PARAMETERS: Node - Parent Node - * Object - Object to be attached - * Type - Type of object, or ACPI_TYPE_ANY if not - * known - * - * RETURN: Status - * - * DESCRIPTION: Record the given object as the value associated with the - * name whose acpi_handle is passed. If Object is NULL - * and Type is ACPI_TYPE_ANY, set the name as having no value. - * Note: Future may require that the Node->Flags field be passed - * as a parameter. - * - * MUTEX: Assumes namespace is locked - * - ******************************************************************************/ -acpi_status -acpi_ns_attach_object(struct acpi_namespace_node *node, - union acpi_operand_object *object, acpi_object_type type) -{ - union acpi_operand_object *obj_desc; - union acpi_operand_object *last_obj_desc; - acpi_object_type object_type = ACPI_TYPE_ANY; - - ACPI_FUNCTION_TRACE(ns_attach_object); - - /* - * Parameter validation - */ - if (!node) { - - /* Invalid handle */ - - ACPI_ERROR((AE_INFO, "Null NamedObj handle")); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (!object && (ACPI_TYPE_ANY != type)) { - - /* Null object */ - - ACPI_ERROR((AE_INFO, - "Null object, but type not ACPI_TYPE_ANY")); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { - - /* Not a name handle */ - - ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]", - node, acpi_ut_get_descriptor_name(node))); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Check if this object is already attached */ - - if (node->object == object) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Obj %p already installed in NameObj %p\n", - object, node)); - - return_ACPI_STATUS(AE_OK); - } - - /* If null object, we will just install it */ - - if (!object) { - obj_desc = NULL; - object_type = ACPI_TYPE_ANY; - } - - /* - * If the source object is a namespace Node with an attached object, - * we will use that (attached) object - */ - else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) && - ((struct acpi_namespace_node *)object)->object) { - /* - * Value passed is a name handle and that name has a - * non-null value. Use that name's value and type. - */ - obj_desc = ((struct acpi_namespace_node *)object)->object; - object_type = ((struct acpi_namespace_node *)object)->type; - } - - /* - * Otherwise, we will use the parameter object, but we must type - * it first - */ - else { - obj_desc = (union acpi_operand_object *)object; - - /* Use the given type */ - - object_type = type; - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n", - obj_desc, node, acpi_ut_get_node_name(node))); - - /* Detach an existing attached object if present */ - - if (node->object) { - acpi_ns_detach_object(node); - } - - if (obj_desc) { - /* - * Must increment the new value's reference count - * (if it is an internal object) - */ - acpi_ut_add_reference(obj_desc); - - /* - * Handle objects with multiple descriptors - walk - * to the end of the descriptor list - */ - last_obj_desc = obj_desc; - while (last_obj_desc->common.next_object) { - last_obj_desc = last_obj_desc->common.next_object; - } - - /* Install the object at the front of the object list */ - - last_obj_desc->common.next_object = node->object; - } - - node->type = (u8) object_type; - node->object = obj_desc; - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_detach_object - * - * PARAMETERS: Node - A Namespace node whose object will be detached - * - * RETURN: None. - * - * DESCRIPTION: Detach/delete an object associated with a namespace node. - * if the object is an allocated object, it is freed. - * Otherwise, the field is simply cleared. - * - ******************************************************************************/ - -void acpi_ns_detach_object(struct acpi_namespace_node *node) -{ - union acpi_operand_object *obj_desc; - - ACPI_FUNCTION_TRACE(ns_detach_object); - - obj_desc = node->object; - - if (!obj_desc || - (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA)) { - return_VOID; - } - - /* Clear the entry in all cases */ - - node->object = NULL; - if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) { - node->object = obj_desc->common.next_object; - if (node->object && - (ACPI_GET_OBJECT_TYPE(node->object) != - ACPI_TYPE_LOCAL_DATA)) { - node->object = node->object->common.next_object; - } - } - - /* Reset the node type to untyped */ - - node->type = ACPI_TYPE_ANY; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n", - node, acpi_ut_get_node_name(node), obj_desc)); - - /* Remove one reference on the object (and all subobjects) */ - - acpi_ut_remove_reference(obj_desc); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_attached_object - * - * PARAMETERS: Node - Namespace node - * - * RETURN: Current value of the object field from the Node whose - * handle is passed - * - * DESCRIPTION: Obtain the object attached to a namespace node. - * - ******************************************************************************/ - -union acpi_operand_object *acpi_ns_get_attached_object(struct - acpi_namespace_node - *node) -{ - ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node); - - if (!node) { - ACPI_WARNING((AE_INFO, "Null Node ptr")); - return_PTR(NULL); - } - - if (!node->object || - ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND) - && (ACPI_GET_DESCRIPTOR_TYPE(node->object) != - ACPI_DESC_TYPE_NAMED)) - || (ACPI_GET_OBJECT_TYPE(node->object) == ACPI_TYPE_LOCAL_DATA)) { - return_PTR(NULL); - } - - return_PTR(node->object); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_secondary_object - * - * PARAMETERS: Node - Namespace node - * - * RETURN: Current value of the object field from the Node whose - * handle is passed. - * - * DESCRIPTION: Obtain a secondary object associated with a namespace node. - * - ******************************************************************************/ - -union acpi_operand_object *acpi_ns_get_secondary_object(union - acpi_operand_object - *obj_desc) -{ - ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc); - - if ((!obj_desc) || - (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) || - (!obj_desc->common.next_object) || - (ACPI_GET_OBJECT_TYPE(obj_desc->common.next_object) == - ACPI_TYPE_LOCAL_DATA)) { - return_PTR(NULL); - } - - return_PTR(obj_desc->common.next_object); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_attach_data - * - * PARAMETERS: Node - Namespace node - * Handler - Handler to be associated with the data - * Data - Data to be attached - * - * RETURN: Status - * - * DESCRIPTION: Low-level attach data. Create and attach a Data object. - * - ******************************************************************************/ - -acpi_status -acpi_ns_attach_data(struct acpi_namespace_node *node, - acpi_object_handler handler, void *data) -{ - union acpi_operand_object *prev_obj_desc; - union acpi_operand_object *obj_desc; - union acpi_operand_object *data_desc; - - /* We only allow one attachment per handler */ - - prev_obj_desc = NULL; - obj_desc = node->object; - while (obj_desc) { - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && - (obj_desc->data.handler == handler)) { - return (AE_ALREADY_EXISTS); - } - - prev_obj_desc = obj_desc; - obj_desc = obj_desc->common.next_object; - } - - /* Create an internal object for the data */ - - data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA); - if (!data_desc) { - return (AE_NO_MEMORY); - } - - data_desc->data.handler = handler; - data_desc->data.pointer = data; - - /* Install the data object */ - - if (prev_obj_desc) { - prev_obj_desc->common.next_object = data_desc; - } else { - node->object = data_desc; - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_detach_data - * - * PARAMETERS: Node - Namespace node - * Handler - Handler associated with the data - * - * RETURN: Status - * - * DESCRIPTION: Low-level detach data. Delete the data node, but the caller - * is responsible for the actual data. - * - ******************************************************************************/ - -acpi_status -acpi_ns_detach_data(struct acpi_namespace_node * node, - acpi_object_handler handler) -{ - union acpi_operand_object *obj_desc; - union acpi_operand_object *prev_obj_desc; - - prev_obj_desc = NULL; - obj_desc = node->object; - while (obj_desc) { - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && - (obj_desc->data.handler == handler)) { - if (prev_obj_desc) { - prev_obj_desc->common.next_object = - obj_desc->common.next_object; - } else { - node->object = obj_desc->common.next_object; - } - - acpi_ut_remove_reference(obj_desc); - return (AE_OK); - } - - prev_obj_desc = obj_desc; - obj_desc = obj_desc->common.next_object; - } - - return (AE_NOT_FOUND); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_attached_data - * - * PARAMETERS: Node - Namespace node - * Handler - Handler associated with the data - * Data - Where the data is returned - * - * RETURN: Status - * - * DESCRIPTION: Low level interface to obtain data previously associated with - * a namespace node. - * - ******************************************************************************/ - -acpi_status -acpi_ns_get_attached_data(struct acpi_namespace_node * node, - acpi_object_handler handler, void **data) -{ - union acpi_operand_object *obj_desc; - - obj_desc = node->object; - while (obj_desc) { - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && - (obj_desc->data.handler == handler)) { - *data = obj_desc->data.pointer; - return (AE_OK); - } - - obj_desc = obj_desc->common.next_object; - } - - return (AE_NOT_FOUND); -} diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c deleted file mode 100644 index bcfcf427c909..000000000000 --- a/drivers/acpi/namespace/nsparse.c +++ /dev/null @@ -1,204 +0,0 @@ -/****************************************************************************** - * - * Module Name: nsparse - namespace interface to AML parser - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsparse") - -/******************************************************************************* - * - * FUNCTION: ns_one_complete_parse - * - * PARAMETERS: pass_number - 1 or 2 - * table_desc - The table to be parsed. - * - * RETURN: Status - * - * DESCRIPTION: Perform one complete parse of an ACPI/AML table. - * - ******************************************************************************/ -acpi_status -acpi_ns_one_complete_parse(u32 pass_number, - u32 table_index, - struct acpi_namespace_node *start_node) -{ - union acpi_parse_object *parse_root; - acpi_status status; - u32 aml_length; - u8 *aml_start; - struct acpi_walk_state *walk_state; - struct acpi_table_header *table; - acpi_owner_id owner_id; - - ACPI_FUNCTION_TRACE(ns_one_complete_parse); - - status = acpi_tb_get_owner_id(table_index, &owner_id); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Create and init a Root Node */ - - parse_root = acpi_ps_create_scope_op(); - if (!parse_root) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Create and initialize a new walk state */ - - walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL); - if (!walk_state) { - acpi_ps_free_op(parse_root); - return_ACPI_STATUS(AE_NO_MEMORY); - } - - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - acpi_ps_free_op(parse_root); - return_ACPI_STATUS(status); - } - - /* Table must consist of at least a complete header */ - - if (table->length < sizeof(struct acpi_table_header)) { - status = AE_BAD_HEADER; - } else { - aml_start = (u8 *) table + sizeof(struct acpi_table_header); - aml_length = table->length - sizeof(struct acpi_table_header); - status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, - aml_start, aml_length, NULL, - (u8) pass_number); - } - - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - goto cleanup; - } - - /* start_node is the default location to load the table */ - - if (start_node && start_node != acpi_gbl_root_node) { - status = - acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD, - walk_state); - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - goto cleanup; - } - } - - /* Parse the AML */ - - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %d parse\n", - (unsigned)pass_number)); - status = acpi_ps_parse_aml(walk_state); - - cleanup: - acpi_ps_delete_parse_tree(parse_root); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_parse_table - * - * PARAMETERS: table_desc - An ACPI table descriptor for table to parse - * start_node - Where to enter the table into the namespace - * - * RETURN: Status - * - * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops - * - ******************************************************************************/ - -acpi_status -acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ns_parse_table); - - /* - * AML Parse, pass 1 - * - * In this pass, we load most of the namespace. Control methods - * are not parsed until later. A parse tree is not created. Instead, - * each Parser Op subtree is deleted when it is finished. This saves - * a great deal of memory, and allows a small cache of parse objects - * to service the entire parse. The second pass of the parse then - * performs another complete parse of the AML. - */ - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); - status = - acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index, - start_node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * AML Parse, pass 2 - * - * In this pass, we resolve forward references and other things - * that could not be completed during the first pass. - * Another complete parse of the AML is performed, but the - * overhead of this is compensated for by the fact that the - * parse objects are all cached. - */ - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); - status = - acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index, - start_node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/namespace/nspredef.c b/drivers/acpi/namespace/nspredef.c deleted file mode 100644 index 1e682d03f620..000000000000 --- a/drivers/acpi/namespace/nspredef.c +++ /dev/null @@ -1,1065 +0,0 @@ -/****************************************************************************** - * - * Module Name: nspredef - Validation of ACPI predefined methods and objects - * $Revision: 1.1 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nspredef") - -/******************************************************************************* - * - * This module validates predefined ACPI objects that appear in the namespace, - * at the time they are evaluated (via acpi_evaluate_object). The purpose of this - * validation is to detect problems with BIOS-exposed predefined ACPI objects - * before the results are returned to the ACPI-related drivers. - * - * There are several areas that are validated: - * - * 1) The number of input arguments as defined by the method/object in the - * ASL is validated against the ACPI specification. - * 2) The type of the return object (if any) is validated against the ACPI - * specification. - * 3) For returned package objects, the count of package elements is - * validated, as well as the type of each package element. Nested - * packages are supported. - * - * For any problems found, a warning message is issued. - * - ******************************************************************************/ -/* Local prototypes */ -static acpi_status -acpi_ns_check_package(char *pathname, - union acpi_operand_object **return_object_ptr, - const union acpi_predefined_info *predefined); - -static acpi_status -acpi_ns_check_package_elements(char *pathname, - union acpi_operand_object **elements, - u8 type1, u32 count1, u8 type2, u32 count2); - -static acpi_status -acpi_ns_check_object_type(char *pathname, - union acpi_operand_object **return_object_ptr, - u32 expected_btypes, u32 package_index); - -static acpi_status -acpi_ns_check_reference(char *pathname, - union acpi_operand_object *return_object); - -static acpi_status -acpi_ns_repair_object(u32 expected_btypes, - u32 package_index, - union acpi_operand_object **return_object_ptr); - -/* - * Names for the types that can be returned by the predefined objects. - * Used for warning messages. Must be in the same order as the ACPI_RTYPEs - */ -static const char *acpi_rtype_names[] = { - "/Integer", - "/String", - "/Buffer", - "/Package", - "/Reference", -}; - -#define ACPI_NOT_PACKAGE ACPI_UINT32_MAX - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_predefined_names - * - * PARAMETERS: Node - Namespace node for the method/object - * return_object_ptr - Pointer to the object returned from the - * evaluation of a method or object - * - * RETURN: Status - * - * DESCRIPTION: Check an ACPI name for a match in the predefined name list. - * - ******************************************************************************/ - -acpi_status -acpi_ns_check_predefined_names(struct acpi_namespace_node *node, - u32 user_param_count, - acpi_status return_status, - union acpi_operand_object **return_object_ptr) -{ - union acpi_operand_object *return_object = *return_object_ptr; - acpi_status status = AE_OK; - const union acpi_predefined_info *predefined; - char *pathname; - - /* Match the name for this method/object against the predefined list */ - - predefined = acpi_ns_check_for_predefined_name(node); - - /* Get the full pathname to the object, for use in error messages */ - - pathname = acpi_ns_get_external_pathname(node); - if (!pathname) { - pathname = ACPI_CAST_PTR(char, predefined->info.name); - } - - /* - * Check that the parameter count for this method matches the ASL - * definition. For predefined names, ensure that both the caller and - * the method itself are in accordance with the ACPI specification. - */ - acpi_ns_check_parameter_count(pathname, node, user_param_count, - predefined); - - /* If not a predefined name, we cannot validate the return object */ - - if (!predefined) { - goto exit; - } - - /* If the method failed, we cannot validate the return object */ - - if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { - goto exit; - } - - /* - * Only validate the return value on the first successful evaluation of - * the method. This ensures that any warnings will only be emitted during - * the very first evaluation of the method/object. - */ - if (node->flags & ANOBJ_EVALUATED) { - goto exit; - } - - /* Mark the node as having been successfully evaluated */ - - node->flags |= ANOBJ_EVALUATED; - - /* - * If there is no return value, check if we require a return value for - * this predefined name. Either one return value is expected, or none, - * for both methods and other objects. - * - * Exit now if there is no return object. Warning if one was expected. - */ - if (!return_object) { - if ((predefined->info.expected_btypes) && - (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) { - ACPI_ERROR((AE_INFO, - "%s: Missing expected return value", - pathname)); - - status = AE_AML_NO_RETURN_VALUE; - } - goto exit; - } - - /* - * We have a return value, but if one wasn't expected, just exit, this is - * not a problem - * - * For example, if the "Implicit Return" feature is enabled, methods will - * always return a value - */ - if (!predefined->info.expected_btypes) { - goto exit; - } - - /* - * Check that the type of the return object is what is expected for - * this predefined name - */ - status = acpi_ns_check_object_type(pathname, return_object_ptr, - predefined->info.expected_btypes, - ACPI_NOT_PACKAGE); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* For returned Package objects, check the type of all sub-objects */ - - if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) { - status = - acpi_ns_check_package(pathname, return_object_ptr, - predefined); - } - - exit: - if (pathname != predefined->info.name) { - ACPI_FREE(pathname); - } - - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_parameter_count - * - * PARAMETERS: Pathname - Full pathname to the node (for error msgs) - * Node - Namespace node for the method/object - * user_param_count - Number of args passed in by the caller - * Predefined - Pointer to entry in predefined name table - * - * RETURN: None - * - * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a - * predefined name is what is expected (i.e., what is defined in - * the ACPI specification for this predefined name.) - * - ******************************************************************************/ - -void -acpi_ns_check_parameter_count(char *pathname, - struct acpi_namespace_node *node, - u32 user_param_count, - const union acpi_predefined_info *predefined) -{ - u32 param_count; - u32 required_params_current; - u32 required_params_old; - - /* Methods have 0-7 parameters. All other types have zero. */ - - param_count = 0; - if (node->type == ACPI_TYPE_METHOD) { - param_count = node->object->method.param_count; - } - - /* Argument count check for non-predefined methods/objects */ - - if (!predefined) { - /* - * Warning if too few or too many arguments have been passed by the - * caller. An incorrect number of arguments may not cause the method - * to fail. However, the method will fail if there are too few - * arguments and the method attempts to use one of the missing ones. - */ - if (user_param_count < param_count) { - ACPI_WARNING((AE_INFO, - "%s: Insufficient arguments - needs %d, found %d", - pathname, param_count, user_param_count)); - } else if (user_param_count > param_count) { - ACPI_WARNING((AE_INFO, - "%s: Excess arguments - needs %d, found %d", - pathname, param_count, user_param_count)); - } - return; - } - - /* Allow two different legal argument counts (_SCP, etc.) */ - - required_params_current = predefined->info.param_count & 0x0F; - required_params_old = predefined->info.param_count >> 4; - - if (user_param_count != ACPI_UINT32_MAX) { - - /* Validate the user-supplied parameter count */ - - if ((user_param_count != required_params_current) && - (user_param_count != required_params_old)) { - ACPI_WARNING((AE_INFO, - "%s: Parameter count mismatch - caller passed %d, ACPI requires %d", - pathname, user_param_count, - required_params_current)); - } - } - - /* - * Only validate the argument count on the first successful evaluation of - * the method. This ensures that any warnings will only be emitted during - * the very first evaluation of the method/object. - */ - if (node->flags & ANOBJ_EVALUATED) { - return; - } - - /* - * Check that the ASL-defined parameter count is what is expected for - * this predefined name. - */ - if ((param_count != required_params_current) && - (param_count != required_params_old)) { - ACPI_WARNING((AE_INFO, - "%s: Parameter count mismatch - ASL declared %d, ACPI requires %d", - pathname, param_count, required_params_current)); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_for_predefined_name - * - * PARAMETERS: Node - Namespace node for the method/object - * - * RETURN: Pointer to entry in predefined table. NULL indicates not found. - * - * DESCRIPTION: Check an object name against the predefined object list. - * - ******************************************************************************/ - -const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct - acpi_namespace_node - *node) -{ - const union acpi_predefined_info *this_name; - - /* Quick check for a predefined name, first character must be underscore */ - - if (node->name.ascii[0] != '_') { - return (NULL); - } - - /* Search info table for a predefined method/object name */ - - this_name = predefined_names; - while (this_name->info.name[0]) { - if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) { - - /* Return pointer to this table entry */ - - return (this_name); - } - - /* - * Skip next entry in the table if this name returns a Package - * (next entry contains the package info) - */ - if (this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) { - this_name++; - } - - this_name++; - } - - return (NULL); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_package - * - * PARAMETERS: Pathname - Full pathname to the node (for error msgs) - * return_object_ptr - Pointer to the object returned from the - * evaluation of a method or object - * Predefined - Pointer to entry in predefined name table - * - * RETURN: Status - * - * DESCRIPTION: Check a returned package object for the correct count and - * correct type of all sub-objects. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package(char *pathname, - union acpi_operand_object **return_object_ptr, - const union acpi_predefined_info *predefined) -{ - union acpi_operand_object *return_object = *return_object_ptr; - const union acpi_predefined_info *package; - union acpi_operand_object *sub_package; - union acpi_operand_object **elements; - union acpi_operand_object **sub_elements; - acpi_status status; - u32 expected_count; - u32 count; - u32 i; - u32 j; - - ACPI_FUNCTION_NAME(ns_check_package); - - /* The package info for this name is in the next table entry */ - - package = predefined + 1; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "%s Validating return Package of Type %X, Count %X\n", - pathname, package->ret_info.type, - return_object->package.count)); - - /* Extract package count and elements array */ - - elements = return_object->package.elements; - count = return_object->package.count; - - /* The package must have at least one element, else invalid */ - - if (!count) { - ACPI_WARNING((AE_INFO, - "%s: Return Package has no elements (empty)", - pathname)); - - return (AE_AML_OPERAND_VALUE); - } - - /* - * Decode the type of the expected package contents - * - * PTYPE1 packages contain no subpackages - * PTYPE2 packages contain sub-packages - */ - switch (package->ret_info.type) { - case ACPI_PTYPE1_FIXED: - - /* - * The package count is fixed and there are no sub-packages - * - * If package is too small, exit. - * If package is larger than expected, issue warning but continue - */ - expected_count = - package->ret_info.count1 + package->ret_info.count2; - if (count < expected_count) { - goto package_too_small; - } else if (count > expected_count) { - ACPI_WARNING((AE_INFO, - "%s: Return Package is larger than needed - " - "found %u, expected %u", pathname, count, - expected_count)); - } - - /* Validate all elements of the returned package */ - - status = acpi_ns_check_package_elements(pathname, elements, - package->ret_info. - object_type1, - package->ret_info. - count1, - package->ret_info. - object_type2, - package->ret_info. - count2); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE1_VAR: - - /* - * The package count is variable, there are no sub-packages, and all - * elements must be of the same type - */ - for (i = 0; i < count; i++) { - status = acpi_ns_check_object_type(pathname, elements, - package->ret_info. - object_type1, i); - if (ACPI_FAILURE(status)) { - return (status); - } - elements++; - } - break; - - case ACPI_PTYPE1_OPTION: - - /* - * The package count is variable, there are no sub-packages. There are - * a fixed number of required elements, and a variable number of - * optional elements. - * - * Check if package is at least as large as the minimum required - */ - expected_count = package->ret_info3.count; - if (count < expected_count) { - goto package_too_small; - } - - /* Variable number of sub-objects */ - - for (i = 0; i < count; i++) { - if (i < package->ret_info3.count) { - - /* These are the required package elements (0, 1, or 2) */ - - status = - acpi_ns_check_object_type(pathname, - elements, - package-> - ret_info3. - object_type[i], - i); - if (ACPI_FAILURE(status)) { - return (status); - } - } else { - /* These are the optional package elements */ - - status = - acpi_ns_check_object_type(pathname, - elements, - package-> - ret_info3. - tail_object_type, - i); - if (ACPI_FAILURE(status)) { - return (status); - } - } - elements++; - } - break; - - case ACPI_PTYPE2_PKG_COUNT: - - /* First element is the (Integer) count of sub-packages to follow */ - - status = acpi_ns_check_object_type(pathname, elements, - ACPI_RTYPE_INTEGER, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Count cannot be larger than the parent package length, but allow it - * to be smaller. The >= accounts for the Integer above. - */ - expected_count = (u32) (*elements)->integer.value; - if (expected_count >= count) { - goto package_too_small; - } - - count = expected_count; - elements++; - - /* Now we can walk the sub-packages */ - - /*lint -fallthrough */ - - case ACPI_PTYPE2: - case ACPI_PTYPE2_FIXED: - case ACPI_PTYPE2_MIN: - case ACPI_PTYPE2_COUNT: - - /* - * These types all return a single package that consists of a variable - * number of sub-packages - */ - for (i = 0; i < count; i++) { - sub_package = *elements; - sub_elements = sub_package->package.elements; - - /* Each sub-object must be of type Package */ - - status = - acpi_ns_check_object_type(pathname, &sub_package, - ACPI_RTYPE_PACKAGE, i); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Examine the different types of sub-packages */ - - switch (package->ret_info.type) { - case ACPI_PTYPE2: - case ACPI_PTYPE2_PKG_COUNT: - - /* Each subpackage has a fixed number of elements */ - - expected_count = - package->ret_info.count1 + - package->ret_info.count2; - if (sub_package->package.count != - expected_count) { - count = sub_package->package.count; - goto package_too_small; - } - - status = - acpi_ns_check_package_elements(pathname, - sub_elements, - package-> - ret_info. - object_type1, - package-> - ret_info. - count1, - package-> - ret_info. - object_type2, - package-> - ret_info. - count2); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE2_FIXED: - - /* Each sub-package has a fixed length */ - - expected_count = package->ret_info2.count; - if (sub_package->package.count < expected_count) { - count = sub_package->package.count; - goto package_too_small; - } - - /* Check the type of each sub-package element */ - - for (j = 0; j < expected_count; j++) { - status = - acpi_ns_check_object_type(pathname, - &sub_elements[j], - package->ret_info2.object_type[j], j); - if (ACPI_FAILURE(status)) { - return (status); - } - } - break; - - case ACPI_PTYPE2_MIN: - - /* Each sub-package has a variable but minimum length */ - - expected_count = package->ret_info.count1; - if (sub_package->package.count < expected_count) { - count = sub_package->package.count; - goto package_too_small; - } - - /* Check the type of each sub-package element */ - - status = - acpi_ns_check_package_elements(pathname, - sub_elements, - package-> - ret_info. - object_type1, - sub_package-> - package. - count, 0, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE2_COUNT: - - /* First element is the (Integer) count of elements to follow */ - - status = - acpi_ns_check_object_type(pathname, - sub_elements, - ACPI_RTYPE_INTEGER, - 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Make sure package is large enough for the Count */ - - expected_count = - (u32) (*sub_elements)->integer.value; - if (sub_package->package.count < expected_count) { - count = sub_package->package.count; - goto package_too_small; - } - - /* Check the type of each sub-package element */ - - status = - acpi_ns_check_package_elements(pathname, - (sub_elements - + 1), - package-> - ret_info. - object_type1, - (expected_count - - 1), 0, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - default: - break; - } - - elements++; - } - break; - - default: - - /* Should not get here if predefined info table is correct */ - - ACPI_WARNING((AE_INFO, - "%s: Invalid internal return type in table entry: %X", - pathname, package->ret_info.type)); - - return (AE_AML_INTERNAL); - } - - return (AE_OK); - - package_too_small: - - /* Error exit for the case with an incorrect package count */ - - ACPI_WARNING((AE_INFO, "%s: Return Package is too small - " - "found %u, expected %u", pathname, count, - expected_count)); - - return (AE_AML_OPERAND_VALUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_package_elements - * - * PARAMETERS: Pathname - Full pathname to the node (for error msgs) - * Elements - Pointer to the package elements array - * Type1 - Object type for first group - * Count1 - Count for first group - * Type2 - Object type for second group - * Count2 - Count for second group - * - * RETURN: Status - * - * DESCRIPTION: Check that all elements of a package are of the correct object - * type. Supports up to two groups of different object types. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package_elements(char *pathname, - union acpi_operand_object **elements, - u8 type1, u32 count1, u8 type2, u32 count2) -{ - union acpi_operand_object **this_element = elements; - acpi_status status; - u32 i; - - /* - * Up to two groups of package elements are supported by the data - * structure. All elements in each group must be of the same type. - * The second group can have a count of zero. - */ - for (i = 0; i < count1; i++) { - status = acpi_ns_check_object_type(pathname, this_element, - type1, i); - if (ACPI_FAILURE(status)) { - return (status); - } - this_element++; - } - - for (i = 0; i < count2; i++) { - status = acpi_ns_check_object_type(pathname, this_element, - type2, (i + count1)); - if (ACPI_FAILURE(status)) { - return (status); - } - this_element++; - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_object_type - * - * PARAMETERS: Pathname - Full pathname to the node (for error msgs) - * return_object_ptr - Pointer to the object returned from the - * evaluation of a method or object - * expected_btypes - Bitmap of expected return type(s) - * package_index - Index of object within parent package (if - * applicable - ACPI_NOT_PACKAGE otherwise) - * - * RETURN: Status - * - * DESCRIPTION: Check the type of the return object against the expected object - * type(s). Use of Btype allows multiple expected object types. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_object_type(char *pathname, - union acpi_operand_object **return_object_ptr, - u32 expected_btypes, u32 package_index) -{ - union acpi_operand_object *return_object = *return_object_ptr; - acpi_status status = AE_OK; - u32 return_btype; - char type_buffer[48]; /* Room for 5 types */ - u32 this_rtype; - u32 i; - u32 j; - - /* - * If we get a NULL return_object here, it is a NULL package element, - * and this is always an error. - */ - if (!return_object) { - goto type_error_exit; - } - - /* A Namespace node should not get here, but make sure */ - - if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { - ACPI_WARNING((AE_INFO, - "%s: Invalid return type - Found a Namespace node [%4.4s] type %s", - pathname, return_object->node.name.ascii, - acpi_ut_get_type_name(return_object->node.type))); - return (AE_AML_OPERAND_TYPE); - } - - /* - * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type. - * The bitmapped type allows multiple possible return types. - * - * Note, the cases below must handle all of the possible types returned - * from all of the predefined names (including elements of returned - * packages) - */ - switch (ACPI_GET_OBJECT_TYPE(return_object)) { - case ACPI_TYPE_INTEGER: - return_btype = ACPI_RTYPE_INTEGER; - break; - - case ACPI_TYPE_BUFFER: - return_btype = ACPI_RTYPE_BUFFER; - break; - - case ACPI_TYPE_STRING: - return_btype = ACPI_RTYPE_STRING; - break; - - case ACPI_TYPE_PACKAGE: - return_btype = ACPI_RTYPE_PACKAGE; - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - return_btype = ACPI_RTYPE_REFERENCE; - break; - - default: - /* Not one of the supported objects, must be incorrect */ - - goto type_error_exit; - } - - /* Is the object one of the expected types? */ - - if (!(return_btype & expected_btypes)) { - - /* Type mismatch -- attempt repair of the returned object */ - - status = acpi_ns_repair_object(expected_btypes, package_index, - return_object_ptr); - if (ACPI_SUCCESS(status)) { - return (status); - } - goto type_error_exit; - } - - /* For reference objects, check that the reference type is correct */ - - if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_LOCAL_REFERENCE) { - status = acpi_ns_check_reference(pathname, return_object); - } - - return (status); - - type_error_exit: - - /* Create a string with all expected types for this predefined object */ - - j = 1; - type_buffer[0] = 0; - this_rtype = ACPI_RTYPE_INTEGER; - - for (i = 0; i < ACPI_NUM_RTYPES; i++) { - - /* If one of the expected types, concatenate the name of this type */ - - if (expected_btypes & this_rtype) { - ACPI_STRCAT(type_buffer, &acpi_rtype_names[i][j]); - j = 0; /* Use name separator from now on */ - } - this_rtype <<= 1; /* Next Rtype */ - } - - if (package_index == ACPI_NOT_PACKAGE) { - ACPI_WARNING((AE_INFO, - "%s: Return type mismatch - found %s, expected %s", - pathname, - acpi_ut_get_object_type_name(return_object), - type_buffer)); - } else { - ACPI_WARNING((AE_INFO, - "%s: Return Package type mismatch at index %u - " - "found %s, expected %s", pathname, package_index, - acpi_ut_get_object_type_name(return_object), - type_buffer)); - } - - return (AE_AML_OPERAND_TYPE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_reference - * - * PARAMETERS: Pathname - Full pathname to the node (for error msgs) - * return_object - Object returned from the evaluation of a - * method or object - * - * RETURN: Status - * - * DESCRIPTION: Check a returned reference object for the correct reference - * type. The only reference type that can be returned from a - * predefined method is a named reference. All others are invalid. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_reference(char *pathname, - union acpi_operand_object *return_object) -{ - - /* - * Check the reference object for the correct reference type (opcode). - * The only type of reference that can be converted to an union acpi_object is - * a reference to a named object (reference class: NAME) - */ - if (return_object->reference.class == ACPI_REFCLASS_NAME) { - return (AE_OK); - } - - ACPI_WARNING((AE_INFO, - "%s: Return type mismatch - unexpected reference object type [%s] %2.2X", - pathname, acpi_ut_get_reference_name(return_object), - return_object->reference.class)); - - return (AE_AML_OPERAND_TYPE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_repair_object - * - * PARAMETERS: Pathname - Full pathname to the node (for error msgs) - * package_index - Used to determine if target is in a package - * return_object_ptr - Pointer to the object returned from the - * evaluation of a method or object - * - * RETURN: Status. AE_OK if repair was successful. - * - * DESCRIPTION: Attempt to repair/convert a return object of a type that was - * not expected. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_repair_object(u32 expected_btypes, - u32 package_index, - union acpi_operand_object **return_object_ptr) -{ - union acpi_operand_object *return_object = *return_object_ptr; - union acpi_operand_object *new_object; - acpi_size length; - - switch (ACPI_GET_OBJECT_TYPE(return_object)) { - case ACPI_TYPE_BUFFER: - - if (!(expected_btypes & ACPI_RTYPE_STRING)) { - return (AE_AML_OPERAND_TYPE); - } - - /* - * Have a Buffer, expected a String, convert. Use a to_string - * conversion, no transform performed on the buffer data. The best - * example of this is the _BIF method, where the string data from - * the battery is often (incorrectly) returned as buffer object(s). - */ - length = 0; - while ((length < return_object->buffer.length) && - (return_object->buffer.pointer[length])) { - length++; - } - - /* Allocate a new string object */ - - new_object = acpi_ut_create_string_object(length); - if (!new_object) { - return (AE_NO_MEMORY); - } - - /* - * Copy the raw buffer data with no transform. String is already NULL - * terminated at Length+1. - */ - ACPI_MEMCPY(new_object->string.pointer, - return_object->buffer.pointer, length); - - /* Install the new return object */ - - acpi_ut_remove_reference(return_object); - *return_object_ptr = new_object; - - /* - * If the object is a package element, we need to: - * 1. Decrement the reference count of the orignal object, it was - * incremented when building the package - * 2. Increment the reference count of the new object, it will be - * decremented when releasing the package - */ - if (package_index != ACPI_NOT_PACKAGE) { - acpi_ut_remove_reference(return_object); - acpi_ut_add_reference(new_object); - } - return (AE_OK); - - default: - break; - } - - return (AE_AML_OPERAND_TYPE); -} diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c deleted file mode 100644 index a76c731e3ba5..000000000000 --- a/drivers/acpi/namespace/nssearch.c +++ /dev/null @@ -1,415 +0,0 @@ -/******************************************************************************* - * - * Module Name: nssearch - Namespace search - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nssearch") - -/* Local prototypes */ -static acpi_status -acpi_ns_search_parent_tree(u32 target_name, - struct acpi_namespace_node *node, - acpi_object_type type, - struct acpi_namespace_node **return_node); - -/******************************************************************************* - * - * FUNCTION: acpi_ns_search_one_scope - * - * PARAMETERS: target_name - Ascii ACPI name to search for - * parent_node - Starting node where search will begin - * Type - Object type to match - * return_node - Where the matched Named obj is returned - * - * RETURN: Status - * - * DESCRIPTION: Search a single level of the namespace. Performs a - * simple search of the specified level, and does not add - * entries or search parents. - * - * - * Named object lists are built (and subsequently dumped) in the - * order in which the names are encountered during the namespace load; - * - * All namespace searching is linear in this implementation, but - * could be easily modified to support any improved search - * algorithm. However, the linear search was chosen for simplicity - * and because the trees are small and the other interpreter - * execution overhead is relatively high. - * - * Note: CPU execution analysis has shown that the AML interpreter spends - * a very small percentage of its time searching the namespace. Therefore, - * the linear search seems to be sufficient, as there would seem to be - * little value in improving the search. - * - ******************************************************************************/ - -acpi_status -acpi_ns_search_one_scope(u32 target_name, - struct acpi_namespace_node *parent_node, - acpi_object_type type, - struct acpi_namespace_node **return_node) -{ - struct acpi_namespace_node *node; - - ACPI_FUNCTION_TRACE(ns_search_one_scope); - -#ifdef ACPI_DEBUG_OUTPUT - if (ACPI_LV_NAMES & acpi_dbg_level) { - char *scope_name; - - scope_name = acpi_ns_get_external_pathname(parent_node); - if (scope_name) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Searching %s (%p) For [%4.4s] (%s)\n", - scope_name, parent_node, - ACPI_CAST_PTR(char, &target_name), - acpi_ut_get_type_name(type))); - - ACPI_FREE(scope_name); - } - } -#endif - - /* - * Search for name at this namespace level, which is to say that we - * must search for the name among the children of this object - */ - node = parent_node->child; - while (node) { - - /* Check for match against the name */ - - if (node->name.integer == target_name) { - - /* Resolve a control method alias if any */ - - if (acpi_ns_get_type(node) == - ACPI_TYPE_LOCAL_METHOD_ALIAS) { - node = - ACPI_CAST_PTR(struct acpi_namespace_node, - node->object); - } - - /* Found matching entry */ - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n", - ACPI_CAST_PTR(char, &target_name), - acpi_ut_get_type_name(node->type), - node, - acpi_ut_get_node_name(parent_node), - parent_node)); - - *return_node = node; - return_ACPI_STATUS(AE_OK); - } - - /* - * The last entry in the list points back to the parent, - * so a flag is used to indicate the end-of-list - */ - if (node->flags & ANOBJ_END_OF_PEER_LIST) { - - /* Searched entire list, we are done */ - - break; - } - - /* Didn't match name, move on to the next peer object */ - - node = node->peer; - } - - /* Searched entire namespace level, not found */ - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n", - ACPI_CAST_PTR(char, &target_name), - acpi_ut_get_type_name(type), - acpi_ut_get_node_name(parent_node), parent_node, - parent_node->child)); - - return_ACPI_STATUS(AE_NOT_FOUND); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_search_parent_tree - * - * PARAMETERS: target_name - Ascii ACPI name to search for - * Node - Starting node where search will begin - * Type - Object type to match - * return_node - Where the matched Node is returned - * - * RETURN: Status - * - * DESCRIPTION: Called when a name has not been found in the current namespace - * level. Before adding it or giving up, ACPI scope rules require - * searching enclosing scopes in cases identified by acpi_ns_local(). - * - * "A name is located by finding the matching name in the current - * name space, and then in the parent name space. If the parent - * name space does not contain the name, the search continues - * recursively until either the name is found or the name space - * does not have a parent (the root of the name space). This - * indicates that the name is not found" (From ACPI Specification, - * section 5.3) - * - ******************************************************************************/ - -static acpi_status -acpi_ns_search_parent_tree(u32 target_name, - struct acpi_namespace_node *node, - acpi_object_type type, - struct acpi_namespace_node **return_node) -{ - acpi_status status; - struct acpi_namespace_node *parent_node; - - ACPI_FUNCTION_TRACE(ns_search_parent_tree); - - parent_node = acpi_ns_get_parent_node(node); - - /* - * If there is no parent (i.e., we are at the root) or type is "local", - * we won't be searching the parent tree. - */ - if (!parent_node) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "[%4.4s] has no parent\n", - ACPI_CAST_PTR(char, &target_name))); - return_ACPI_STATUS(AE_NOT_FOUND); - } - - if (acpi_ns_local(type)) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "[%4.4s] type [%s] must be local to this scope (no parent search)\n", - ACPI_CAST_PTR(char, &target_name), - acpi_ut_get_type_name(type))); - return_ACPI_STATUS(AE_NOT_FOUND); - } - - /* Search the parent tree */ - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Searching parent [%4.4s] for [%4.4s]\n", - acpi_ut_get_node_name(parent_node), - ACPI_CAST_PTR(char, &target_name))); - - /* - * Search parents until target is found or we have backed up to the root - */ - while (parent_node) { - /* - * Search parent scope. Use TYPE_ANY because we don't care about the - * object type at this point, we only care about the existence of - * the actual name we are searching for. Typechecking comes later. - */ - status = - acpi_ns_search_one_scope(target_name, parent_node, - ACPI_TYPE_ANY, return_node); - if (ACPI_SUCCESS(status)) { - return_ACPI_STATUS(status); - } - - /* Not found here, go up another level (until we reach the root) */ - - parent_node = acpi_ns_get_parent_node(parent_node); - } - - /* Not found in parent tree */ - - return_ACPI_STATUS(AE_NOT_FOUND); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_search_and_enter - * - * PARAMETERS: target_name - Ascii ACPI name to search for (4 chars) - * walk_state - Current state of the walk - * Node - Starting node where search will begin - * interpreter_mode - Add names only in ACPI_MODE_LOAD_PASS_x. - * Otherwise,search only. - * Type - Object type to match - * Flags - Flags describing the search restrictions - * return_node - Where the Node is returned - * - * RETURN: Status - * - * DESCRIPTION: Search for a name segment in a single namespace level, - * optionally adding it if it is not found. If the passed - * Type is not Any and the type previously stored in the - * entry was Any (i.e. unknown), update the stored type. - * - * In ACPI_IMODE_EXECUTE, search only. - * In other modes, search and add if not found. - * - ******************************************************************************/ - -acpi_status -acpi_ns_search_and_enter(u32 target_name, - struct acpi_walk_state *walk_state, - struct acpi_namespace_node *node, - acpi_interpreter_mode interpreter_mode, - acpi_object_type type, - u32 flags, struct acpi_namespace_node **return_node) -{ - acpi_status status; - struct acpi_namespace_node *new_node; - - ACPI_FUNCTION_TRACE(ns_search_and_enter); - - /* Parameter validation */ - - if (!node || !target_name || !return_node) { - ACPI_ERROR((AE_INFO, - "Null parameter: Node %p Name %X ReturnNode %p", - node, target_name, return_node)); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* - * Name must consist of valid ACPI characters. We will repair the name if - * necessary because we don't want to abort because of this, but we want - * all namespace names to be printable. A warning message is appropriate. - * - * This issue came up because there are in fact machines that exhibit - * this problem, and we want to be able to enable ACPI support for them, - * even though there are a few bad names. - */ - if (!acpi_ut_valid_acpi_name(target_name)) { - target_name = - acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name)); - - /* Report warning only if in strict mode or debug mode */ - - if (!acpi_gbl_enable_interpreter_slack) { - ACPI_WARNING((AE_INFO, - "Found bad character(s) in name, repaired: [%4.4s]\n", - ACPI_CAST_PTR(char, &target_name))); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found bad character(s) in name, repaired: [%4.4s]\n", - ACPI_CAST_PTR(char, &target_name))); - } - } - - /* Try to find the name in the namespace level specified by the caller */ - - *return_node = ACPI_ENTRY_NOT_FOUND; - status = acpi_ns_search_one_scope(target_name, node, type, return_node); - if (status != AE_NOT_FOUND) { - /* - * If we found it AND the request specifies that a find is an error, - * return the error - */ - if ((status == AE_OK) && (flags & ACPI_NS_ERROR_IF_FOUND)) { - status = AE_ALREADY_EXISTS; - } - - /* Either found it or there was an error: finished either way */ - - return_ACPI_STATUS(status); - } - - /* - * The name was not found. If we are NOT performing the first pass - * (name entry) of loading the namespace, search the parent tree (all the - * way to the root if necessary.) We don't want to perform the parent - * search when the namespace is actually being loaded. We want to perform - * the search when namespace references are being resolved (load pass 2) - * and during the execution phase. - */ - if ((interpreter_mode != ACPI_IMODE_LOAD_PASS1) && - (flags & ACPI_NS_SEARCH_PARENT)) { - /* - * Not found at this level - search parent tree according to the - * ACPI specification - */ - status = - acpi_ns_search_parent_tree(target_name, node, type, - return_node); - if (ACPI_SUCCESS(status)) { - return_ACPI_STATUS(status); - } - } - - /* In execute mode, just search, never add names. Exit now */ - - if (interpreter_mode == ACPI_IMODE_EXECUTE) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "%4.4s Not found in %p [Not adding]\n", - ACPI_CAST_PTR(char, &target_name), node)); - - return_ACPI_STATUS(AE_NOT_FOUND); - } - - /* Create the new named object */ - - new_node = acpi_ns_create_node(target_name); - if (!new_node) { - return_ACPI_STATUS(AE_NO_MEMORY); - } -#ifdef ACPI_ASL_COMPILER - /* - * Node is an object defined by an External() statement - */ - if (flags & ACPI_NS_EXTERNAL) { - new_node->flags |= ANOBJ_IS_EXTERNAL; - } -#endif - - if (flags & ACPI_NS_TEMPORARY) { - new_node->flags |= ANOBJ_TEMPORARY; - } - - /* Install the new object into the parent's list of children */ - - acpi_ns_install_node(walk_state, node, new_node, type); - *return_node = new_node; - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c deleted file mode 100644 index a443d2805d2c..000000000000 --- a/drivers/acpi/namespace/nsutils.c +++ /dev/null @@ -1,997 +0,0 @@ -/****************************************************************************** - * - * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing - * parents and siblings and Scope manipulation - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsutils") - -/* Local prototypes */ -static u8 acpi_ns_valid_path_separator(char sep); - -#ifdef ACPI_OBSOLETE_FUNCTIONS -acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ns_report_error - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * internal_name - Name or path of the namespace node - * lookup_status - Exception code from NS lookup - * - * RETURN: None - * - * DESCRIPTION: Print warning message with full pathname - * - ******************************************************************************/ - -void -acpi_ns_report_error(const char *module_name, - u32 line_number, - const char *internal_name, acpi_status lookup_status) -{ - acpi_status status; - u32 bad_name; - char *name = NULL; - - acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); - - if (lookup_status == AE_BAD_CHARACTER) { - - /* There is a non-ascii character in the name */ - - ACPI_MOVE_32_TO_32(&bad_name, internal_name); - acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); - } else { - /* Convert path to external format */ - - status = acpi_ns_externalize_name(ACPI_UINT32_MAX, - internal_name, NULL, &name); - - /* Print target name */ - - if (ACPI_SUCCESS(status)) { - acpi_os_printf("[%s]", name); - } else { - acpi_os_printf("[COULD NOT EXTERNALIZE NAME]"); - } - - if (name) { - ACPI_FREE(name); - } - } - - acpi_os_printf(" Namespace lookup failure, %s\n", - acpi_format_exception(lookup_status)); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_report_method_error - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * Message - Error message to use on failure - * prefix_node - Prefix relative to the path - * Path - Path to the node (optional) - * method_status - Execution status - * - * RETURN: None - * - * DESCRIPTION: Print warning message with full pathname - * - ******************************************************************************/ - -void -acpi_ns_report_method_error(const char *module_name, - u32 line_number, - const char *message, - struct acpi_namespace_node *prefix_node, - const char *path, acpi_status method_status) -{ - acpi_status status; - struct acpi_namespace_node *node = prefix_node; - - acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); - - if (path) { - status = - acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, - &node); - if (ACPI_FAILURE(status)) { - acpi_os_printf("[Could not get node by pathname]"); - } - } - - acpi_ns_print_node_pathname(node, message); - acpi_os_printf(", %s\n", acpi_format_exception(method_status)); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_print_node_pathname - * - * PARAMETERS: Node - Object - * Message - Prefix message - * - * DESCRIPTION: Print an object's full namespace pathname - * Manages allocation/freeing of a pathname buffer - * - ******************************************************************************/ - -void -acpi_ns_print_node_pathname(struct acpi_namespace_node *node, - const char *message) -{ - struct acpi_buffer buffer; - acpi_status status; - - if (!node) { - acpi_os_printf("[NULL NAME]"); - return; - } - - /* Convert handle to full pathname and print it (with supplied message) */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - - status = acpi_ns_handle_to_pathname(node, &buffer); - if (ACPI_SUCCESS(status)) { - if (message) { - acpi_os_printf("%s ", message); - } - - acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node); - ACPI_FREE(buffer.pointer); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_valid_root_prefix - * - * PARAMETERS: Prefix - Character to be checked - * - * RETURN: TRUE if a valid prefix - * - * DESCRIPTION: Check if a character is a valid ACPI Root prefix - * - ******************************************************************************/ - -u8 acpi_ns_valid_root_prefix(char prefix) -{ - - return ((u8) (prefix == '\\')); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_valid_path_separator - * - * PARAMETERS: Sep - Character to be checked - * - * RETURN: TRUE if a valid path separator - * - * DESCRIPTION: Check if a character is a valid ACPI path separator - * - ******************************************************************************/ - -static u8 acpi_ns_valid_path_separator(char sep) -{ - - return ((u8) (sep == '.')); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_type - * - * PARAMETERS: Node - Parent Node to be examined - * - * RETURN: Type field from Node whose handle is passed - * - * DESCRIPTION: Return the type of a Namespace node - * - ******************************************************************************/ - -acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) -{ - ACPI_FUNCTION_TRACE(ns_get_type); - - if (!node) { - ACPI_WARNING((AE_INFO, "Null Node parameter")); - return_UINT32(ACPI_TYPE_ANY); - } - - return_UINT32((acpi_object_type) node->type); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_local - * - * PARAMETERS: Type - A namespace object type - * - * RETURN: LOCAL if names must be found locally in objects of the - * passed type, 0 if enclosing scopes should be searched - * - * DESCRIPTION: Returns scope rule for the given object type. - * - ******************************************************************************/ - -u32 acpi_ns_local(acpi_object_type type) -{ - ACPI_FUNCTION_TRACE(ns_local); - - if (!acpi_ut_valid_object_type(type)) { - - /* Type code out of range */ - - ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); - return_UINT32(ACPI_NS_NORMAL); - } - - return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_internal_name_length - * - * PARAMETERS: Info - Info struct initialized with the - * external name pointer. - * - * RETURN: None - * - * DESCRIPTION: Calculate the length of the internal (AML) namestring - * corresponding to the external (ASL) namestring. - * - ******************************************************************************/ - -void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) -{ - const char *next_external_char; - u32 i; - - ACPI_FUNCTION_ENTRY(); - - next_external_char = info->external_name; - info->num_carats = 0; - info->num_segments = 0; - info->fully_qualified = FALSE; - - /* - * For the internal name, the required length is 4 bytes per segment, plus - * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null - * (which is not really needed, but no there's harm in putting it there) - * - * strlen() + 1 covers the first name_seg, which has no path separator - */ - if (acpi_ns_valid_root_prefix(*next_external_char)) { - info->fully_qualified = TRUE; - next_external_char++; - - /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */ - - while (acpi_ns_valid_root_prefix(*next_external_char)) { - next_external_char++; - } - } else { - /* - * Handle Carat prefixes - */ - while (*next_external_char == '^') { - info->num_carats++; - next_external_char++; - } - } - - /* - * Determine the number of ACPI name "segments" by counting the number of - * path separators within the string. Start with one segment since the - * segment count is [(# separators) + 1], and zero separators is ok. - */ - if (*next_external_char) { - info->num_segments = 1; - for (i = 0; next_external_char[i]; i++) { - if (acpi_ns_valid_path_separator(next_external_char[i])) { - info->num_segments++; - } - } - } - - info->length = (ACPI_NAME_SIZE * info->num_segments) + - 4 + info->num_carats; - - info->next_external_char = next_external_char; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_build_internal_name - * - * PARAMETERS: Info - Info struct fully initialized - * - * RETURN: Status - * - * DESCRIPTION: Construct the internal (AML) namestring - * corresponding to the external (ASL) namestring. - * - ******************************************************************************/ - -acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) -{ - u32 num_segments = info->num_segments; - char *internal_name = info->internal_name; - const char *external_name = info->next_external_char; - char *result = NULL; - u32 i; - - ACPI_FUNCTION_TRACE(ns_build_internal_name); - - /* Setup the correct prefixes, counts, and pointers */ - - if (info->fully_qualified) { - internal_name[0] = '\\'; - - if (num_segments <= 1) { - result = &internal_name[1]; - } else if (num_segments == 2) { - internal_name[1] = AML_DUAL_NAME_PREFIX; - result = &internal_name[2]; - } else { - internal_name[1] = AML_MULTI_NAME_PREFIX_OP; - internal_name[2] = (char)num_segments; - result = &internal_name[3]; - } - } else { - /* - * Not fully qualified. - * Handle Carats first, then append the name segments - */ - i = 0; - if (info->num_carats) { - for (i = 0; i < info->num_carats; i++) { - internal_name[i] = '^'; - } - } - - if (num_segments <= 1) { - result = &internal_name[i]; - } else if (num_segments == 2) { - internal_name[i] = AML_DUAL_NAME_PREFIX; - result = &internal_name[(acpi_size) i + 1]; - } else { - internal_name[i] = AML_MULTI_NAME_PREFIX_OP; - internal_name[(acpi_size) i + 1] = (char)num_segments; - result = &internal_name[(acpi_size) i + 2]; - } - } - - /* Build the name (minus path separators) */ - - for (; num_segments; num_segments--) { - for (i = 0; i < ACPI_NAME_SIZE; i++) { - if (acpi_ns_valid_path_separator(*external_name) || - (*external_name == 0)) { - - /* Pad the segment with underscore(s) if segment is short */ - - result[i] = '_'; - } else { - /* Convert the character to uppercase and save it */ - - result[i] = - (char)ACPI_TOUPPER((int)*external_name); - external_name++; - } - } - - /* Now we must have a path separator, or the pathname is bad */ - - if (!acpi_ns_valid_path_separator(*external_name) && - (*external_name != 0)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Move on the next segment */ - - external_name++; - result += ACPI_NAME_SIZE; - } - - /* Terminate the string */ - - *result = 0; - - if (info->fully_qualified) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Returning [%p] (abs) \"\\%s\"\n", - internal_name, internal_name)); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n", - internal_name, internal_name)); - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_internalize_name - * - * PARAMETERS: *external_name - External representation of name - * **Converted Name - Where to return the resulting - * internal represention of the name - * - * RETURN: Status - * - * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") - * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) - * - *******************************************************************************/ - -acpi_status -acpi_ns_internalize_name(const char *external_name, char **converted_name) -{ - char *internal_name; - struct acpi_namestring_info info; - acpi_status status; - - ACPI_FUNCTION_TRACE(ns_internalize_name); - - if ((!external_name) || (*external_name == 0) || (!converted_name)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Get the length of the new internal name */ - - info.external_name = external_name; - acpi_ns_get_internal_name_length(&info); - - /* We need a segment to store the internal name */ - - internal_name = ACPI_ALLOCATE_ZEROED(info.length); - if (!internal_name) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Build the name */ - - info.internal_name = internal_name; - status = acpi_ns_build_internal_name(&info); - if (ACPI_FAILURE(status)) { - ACPI_FREE(internal_name); - return_ACPI_STATUS(status); - } - - *converted_name = internal_name; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_externalize_name - * - * PARAMETERS: internal_name_length - Lenth of the internal name below - * internal_name - Internal representation of name - * converted_name_length - Where the length is returned - * converted_name - Where the resulting external name - * is returned - * - * RETURN: Status - * - * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) - * to its external (printable) form (e.g. "\_PR_.CPU0") - * - ******************************************************************************/ - -acpi_status -acpi_ns_externalize_name(u32 internal_name_length, - const char *internal_name, - u32 * converted_name_length, char **converted_name) -{ - u32 names_index = 0; - u32 num_segments = 0; - u32 required_length; - u32 prefix_length = 0; - u32 i = 0; - u32 j = 0; - - ACPI_FUNCTION_TRACE(ns_externalize_name); - - if (!internal_name_length || !internal_name || !converted_name) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* - * Check for a prefix (one '\' | one or more '^'). - */ - switch (internal_name[0]) { - case '\\': - prefix_length = 1; - break; - - case '^': - for (i = 0; i < internal_name_length; i++) { - if (internal_name[i] == '^') { - prefix_length = i + 1; - } else { - break; - } - } - - if (i == internal_name_length) { - prefix_length = i; - } - - break; - - default: - break; - } - - /* - * Check for object names. Note that there could be 0-255 of these - * 4-byte elements. - */ - if (prefix_length < internal_name_length) { - switch (internal_name[prefix_length]) { - case AML_MULTI_NAME_PREFIX_OP: - - /* 4-byte names */ - - names_index = prefix_length + 2; - num_segments = (u8) - internal_name[(acpi_size) prefix_length + 1]; - break; - - case AML_DUAL_NAME_PREFIX: - - /* Two 4-byte names */ - - names_index = prefix_length + 1; - num_segments = 2; - break; - - case 0: - - /* null_name */ - - names_index = 0; - num_segments = 0; - break; - - default: - - /* one 4-byte name */ - - names_index = prefix_length; - num_segments = 1; - break; - } - } - - /* - * Calculate the length of converted_name, which equals the length - * of the prefix, length of all object names, length of any required - * punctuation ('.') between object names, plus the NULL terminator. - */ - required_length = prefix_length + (4 * num_segments) + - ((num_segments > 0) ? (num_segments - 1) : 0) + 1; - - /* - * Check to see if we're still in bounds. If not, there's a problem - * with internal_name (invalid format). - */ - if (required_length > internal_name_length) { - ACPI_ERROR((AE_INFO, "Invalid internal name")); - return_ACPI_STATUS(AE_BAD_PATHNAME); - } - - /* - * Build converted_name - */ - *converted_name = ACPI_ALLOCATE_ZEROED(required_length); - if (!(*converted_name)) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - j = 0; - - for (i = 0; i < prefix_length; i++) { - (*converted_name)[j++] = internal_name[i]; - } - - if (num_segments > 0) { - for (i = 0; i < num_segments; i++) { - if (i > 0) { - (*converted_name)[j++] = '.'; - } - - (*converted_name)[j++] = internal_name[names_index++]; - (*converted_name)[j++] = internal_name[names_index++]; - (*converted_name)[j++] = internal_name[names_index++]; - (*converted_name)[j++] = internal_name[names_index++]; - } - } - - if (converted_name_length) { - *converted_name_length = (u32) required_length; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_map_handle_to_node - * - * PARAMETERS: Handle - Handle to be converted to an Node - * - * RETURN: A Name table entry pointer - * - * DESCRIPTION: Convert a namespace handle to a real Node - * - * Note: Real integer handles would allow for more verification - * and keep all pointers within this subsystem - however this introduces - * more (and perhaps unnecessary) overhead. - * - ******************************************************************************/ - -struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) -{ - - ACPI_FUNCTION_ENTRY(); - - /* - * Simple implementation - */ - if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { - return (acpi_gbl_root_node); - } - - /* We can at least attempt to verify the handle */ - - if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) { - return (NULL); - } - - return (ACPI_CAST_PTR(struct acpi_namespace_node, handle)); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_convert_entry_to_handle - * - * PARAMETERS: Node - Node to be converted to a Handle - * - * RETURN: A user handle - * - * DESCRIPTION: Convert a real Node to a namespace handle - * - ******************************************************************************/ - -acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node) -{ - - /* - * Simple implementation for now; - */ - return ((acpi_handle) node); - -/* Example future implementation --------------------- - - if (!Node) - { - return (NULL); - } - - if (Node == acpi_gbl_root_node) - { - return (ACPI_ROOT_OBJECT); - } - - return ((acpi_handle) Node); -------------------------------------------------------*/ -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_terminate - * - * PARAMETERS: none - * - * RETURN: none - * - * DESCRIPTION: free memory allocated for namespace and ACPI table storage. - * - ******************************************************************************/ - -void acpi_ns_terminate(void) -{ - union acpi_operand_object *obj_desc; - - ACPI_FUNCTION_TRACE(ns_terminate); - - /* - * 1) Free the entire namespace -- all nodes and objects - * - * Delete all object descriptors attached to namepsace nodes - */ - acpi_ns_delete_namespace_subtree(acpi_gbl_root_node); - - /* Detach any objects attached to the root */ - - obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node); - if (obj_desc) { - acpi_ns_detach_object(acpi_gbl_root_node); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_opens_scope - * - * PARAMETERS: Type - A valid namespace type - * - * RETURN: NEWSCOPE if the passed type "opens a name scope" according - * to the ACPI specification, else 0 - * - ******************************************************************************/ - -u32 acpi_ns_opens_scope(acpi_object_type type) -{ - ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); - - if (!acpi_ut_valid_object_type(type)) { - - /* type code out of range */ - - ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); - return_UINT32(ACPI_NS_NORMAL); - } - - return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_node - * - * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The - * \ (backslash) and ^ (carat) prefixes, and the - * . (period) to separate segments are supported. - * prefix_node - Root of subtree to be searched, or NS_ALL for the - * root of the name space. If Name is fully - * qualified (first s8 is '\'), the passed value - * of Scope will not be accessed. - * Flags - Used to indicate whether to perform upsearch or - * not. - * return_node - Where the Node is returned - * - * DESCRIPTION: Look up a name relative to a given scope and return the - * corresponding Node. NOTE: Scope can be null. - * - * MUTEX: Locks namespace - * - ******************************************************************************/ - -acpi_status -acpi_ns_get_node(struct acpi_namespace_node *prefix_node, - const char *pathname, - u32 flags, struct acpi_namespace_node **return_node) -{ - union acpi_generic_state scope_info; - acpi_status status; - char *internal_path; - - ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname); - - if (!pathname) { - *return_node = prefix_node; - if (!prefix_node) { - *return_node = acpi_gbl_root_node; - } - return_ACPI_STATUS(AE_OK); - } - - /* Convert path to internal representation */ - - status = acpi_ns_internalize_name(pathname, &internal_path); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Must lock namespace during lookup */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Setup lookup scope (search starting point) */ - - scope_info.scope.node = prefix_node; - - /* Lookup the name in the namespace */ - - status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY, - ACPI_IMODE_EXECUTE, - (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, - return_node); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n", - pathname, acpi_format_exception(status))); - } - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - - cleanup: - ACPI_FREE(internal_path); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_parent_node - * - * PARAMETERS: Node - Current table entry - * - * RETURN: Parent entry of the given entry - * - * DESCRIPTION: Obtain the parent entry for a given entry in the namespace. - * - ******************************************************************************/ - -struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node - *node) -{ - ACPI_FUNCTION_ENTRY(); - - if (!node) { - return (NULL); - } - - /* - * Walk to the end of this peer list. The last entry is marked with a flag - * and the peer pointer is really a pointer back to the parent. This saves - * putting a parent back pointer in each and every named object! - */ - while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) { - node = node->peer; - } - - return (node->peer); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_next_valid_node - * - * PARAMETERS: Node - Current table entry - * - * RETURN: Next valid Node in the linked node list. NULL if no more valid - * nodes. - * - * DESCRIPTION: Find the next valid node within a name table. - * Useful for implementing NULL-end-of-list loops. - * - ******************************************************************************/ - -struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct - acpi_namespace_node - *node) -{ - - /* If we are at the end of this peer list, return NULL */ - - if (node->flags & ANOBJ_END_OF_PEER_LIST) { - return NULL; - } - - /* Otherwise just return the next peer */ - - return (node->peer); -} - -#ifdef ACPI_OBSOLETE_FUNCTIONS -/******************************************************************************* - * - * FUNCTION: acpi_ns_find_parent_name - * - * PARAMETERS: *child_node - Named Obj whose name is to be found - * - * RETURN: The ACPI name - * - * DESCRIPTION: Search for the given obj in its parent scope and return the - * name segment, or "????" if the parent name can't be found - * (which "should not happen"). - * - ******************************************************************************/ - -acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node) -{ - struct acpi_namespace_node *parent_node; - - ACPI_FUNCTION_TRACE(ns_find_parent_name); - - if (child_node) { - - /* Valid entry. Get the parent Node */ - - parent_node = acpi_ns_get_parent_node(child_node); - if (parent_node) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Parent of %p [%4.4s] is %p [%4.4s]\n", - child_node, - acpi_ut_get_node_name(child_node), - parent_node, - acpi_ut_get_node_name(parent_node))); - - if (parent_node->name.integer) { - return_VALUE((acpi_name) parent_node->name. - integer); - } - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Unable to find parent of %p (%4.4s)\n", - child_node, - acpi_ut_get_node_name(child_node))); - } - - return_VALUE(ACPI_UNKNOWN_NAME); -} -#endif diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c deleted file mode 100644 index 71b83e9807da..000000000000 --- a/drivers/acpi/namespace/nswalk.c +++ /dev/null @@ -1,296 +0,0 @@ -/****************************************************************************** - * - * Module Name: nswalk - Functions for walking the ACPI namespace - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nswalk") - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_next_node - * - * PARAMETERS: Type - Type of node to be searched for - * parent_node - Parent node whose children we are - * getting - * child_node - Previous child that was found. - * The NEXT child will be returned - * - * RETURN: struct acpi_namespace_node - Pointer to the NEXT child or NULL if - * none is found. - * - * DESCRIPTION: Return the next peer node within the namespace. If Handle - * is valid, Scope is ignored. Otherwise, the first node - * within Scope is returned. - * - ******************************************************************************/ -struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct acpi_namespace_node - *parent_node, struct acpi_namespace_node - *child_node) -{ - struct acpi_namespace_node *next_node = NULL; - - ACPI_FUNCTION_ENTRY(); - - if (!child_node) { - - /* It's really the parent's _scope_ that we want */ - - next_node = parent_node->child; - } - - else { - /* Start search at the NEXT node */ - - next_node = acpi_ns_get_next_valid_node(child_node); - } - - /* If any type is OK, we are done */ - - if (type == ACPI_TYPE_ANY) { - - /* next_node is NULL if we are at the end-of-list */ - - return (next_node); - } - - /* Must search for the node -- but within this scope only */ - - while (next_node) { - - /* If type matches, we are done */ - - if (next_node->type == type) { - return (next_node); - } - - /* Otherwise, move on to the next node */ - - next_node = acpi_ns_get_next_valid_node(next_node); - } - - /* Not found */ - - return (NULL); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_walk_namespace - * - * PARAMETERS: Type - acpi_object_type to search for - * start_node - Handle in namespace where search begins - * max_depth - Depth to which search is to reach - * Flags - Whether to unlock the NS before invoking - * the callback routine - * user_function - Called when an object of "Type" is found - * Context - Passed to user function - * return_value - from the user_function if terminated early. - * Otherwise, returns NULL. - * RETURNS: Status - * - * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, - * starting (and ending) at the node specified by start_handle. - * The user_function is called whenever a node that matches - * the type parameter is found. If the user function returns - * a non-zero value, the search is terminated immediately and this - * value is returned to the caller. - * - * The point of this procedure is to provide a generic namespace - * walk routine that can be called from multiple places to - * provide multiple services; the User Function can be tailored - * to each task, whether it is a print function, a compare - * function, etc. - * - ******************************************************************************/ - -acpi_status -acpi_ns_walk_namespace(acpi_object_type type, - acpi_handle start_node, - u32 max_depth, - u32 flags, - acpi_walk_callback user_function, - void *context, void **return_value) -{ - acpi_status status; - acpi_status mutex_status; - struct acpi_namespace_node *child_node; - struct acpi_namespace_node *parent_node; - acpi_object_type child_type; - u32 level; - - ACPI_FUNCTION_TRACE(ns_walk_namespace); - - /* Special case for the namespace Root Node */ - - if (start_node == ACPI_ROOT_OBJECT) { - start_node = acpi_gbl_root_node; - } - - /* Null child means "get first node" */ - - parent_node = start_node; - child_node = NULL; - child_type = ACPI_TYPE_ANY; - level = 1; - - /* - * Traverse the tree of nodes until we bubble back up to where we - * started. When Level is zero, the loop is done because we have - * bubbled up to (and passed) the original parent handle (start_entry) - */ - while (level > 0) { - - /* Get the next node in this scope. Null if not found */ - - status = AE_OK; - child_node = - acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, - child_node); - if (child_node) { - - /* Found next child, get the type if we are not searching for ANY */ - - if (type != ACPI_TYPE_ANY) { - child_type = child_node->type; - } - - /* - * Ignore all temporary namespace nodes (created during control - * method execution) unless told otherwise. These temporary nodes - * can cause a race condition because they can be deleted during the - * execution of the user function (if the namespace is unlocked before - * invocation of the user function.) Only the debugger namespace dump - * will examine the temporary nodes. - */ - if ((child_node->flags & ANOBJ_TEMPORARY) && - !(flags & ACPI_NS_WALK_TEMP_NODES)) { - status = AE_CTRL_DEPTH; - } - - /* Type must match requested type */ - - else if (child_type == type) { - /* - * Found a matching node, invoke the user callback function. - * Unlock the namespace if flag is set. - */ - if (flags & ACPI_NS_WALK_UNLOCK) { - mutex_status = - acpi_ut_release_mutex - (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(mutex_status)) { - return_ACPI_STATUS - (mutex_status); - } - } - - status = - user_function(child_node, level, context, - return_value); - - if (flags & ACPI_NS_WALK_UNLOCK) { - mutex_status = - acpi_ut_acquire_mutex - (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(mutex_status)) { - return_ACPI_STATUS - (mutex_status); - } - } - - switch (status) { - case AE_OK: - case AE_CTRL_DEPTH: - - /* Just keep going */ - break; - - case AE_CTRL_TERMINATE: - - /* Exit now, with OK status */ - - return_ACPI_STATUS(AE_OK); - - default: - - /* All others are valid exceptions */ - - return_ACPI_STATUS(status); - } - } - - /* - * Depth first search: Attempt to go down another level in the - * namespace if we are allowed to. Don't go any further if we have - * reached the caller specified maximum depth or if the user - * function has specified that the maximum depth has been reached. - */ - if ((level < max_depth) && (status != AE_CTRL_DEPTH)) { - if (acpi_ns_get_next_node - (ACPI_TYPE_ANY, child_node, NULL)) { - - /* There is at least one child of this node, visit it */ - - level++; - parent_node = child_node; - child_node = NULL; - } - } - } else { - /* - * No more children of this node (acpi_ns_get_next_node failed), go - * back upwards in the namespace tree to the node's parent. - */ - level--; - child_node = parent_node; - parent_node = acpi_ns_get_parent_node(parent_node); - } - } - - /* Complete walk, not terminated by user function */ - - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c deleted file mode 100644 index 598393a04e5f..000000000000 --- a/drivers/acpi/namespace/nsxfeval.c +++ /dev/null @@ -1,812 +0,0 @@ -/******************************************************************************* - * - * Module Name: nsxfeval - Public interfaces to the ACPI subsystem - * ACPI Object evaluation interfaces - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsxfeval") - -/* Local prototypes */ -static void acpi_ns_resolve_references(struct acpi_evaluate_info *info); - -#ifdef ACPI_FUTURE_USAGE -/******************************************************************************* - * - * FUNCTION: acpi_evaluate_object_typed - * - * PARAMETERS: Handle - Object handle (optional) - * Pathname - Object pathname (optional) - * external_params - List of parameters to pass to method, - * terminated by NULL. May be NULL - * if no parameters are being passed. - * return_buffer - Where to put method's return value (if - * any). If NULL, no value is returned. - * return_type - Expected type of return object - * - * RETURN: Status - * - * DESCRIPTION: Find and evaluate the given object, passing the given - * parameters if necessary. One of "Handle" or "Pathname" must - * be valid (non-null) - * - ******************************************************************************/ - -acpi_status -acpi_evaluate_object_typed(acpi_handle handle, - acpi_string pathname, - struct acpi_object_list *external_params, - struct acpi_buffer *return_buffer, - acpi_object_type return_type) -{ - acpi_status status; - u8 must_free = FALSE; - - ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed); - - /* Return buffer must be valid */ - - if (!return_buffer) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { - must_free = TRUE; - } - - /* Evaluate the object */ - - status = - acpi_evaluate_object(handle, pathname, external_params, - return_buffer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Type ANY means "don't care" */ - - if (return_type == ACPI_TYPE_ANY) { - return_ACPI_STATUS(AE_OK); - } - - if (return_buffer->length == 0) { - - /* Error because caller specifically asked for a return value */ - - ACPI_ERROR((AE_INFO, "No return value")); - return_ACPI_STATUS(AE_NULL_OBJECT); - } - - /* Examine the object type returned from evaluate_object */ - - if (((union acpi_object *)return_buffer->pointer)->type == return_type) { - return_ACPI_STATUS(AE_OK); - } - - /* Return object type does not match requested type */ - - ACPI_ERROR((AE_INFO, - "Incorrect return type [%s] requested [%s]", - acpi_ut_get_type_name(((union acpi_object *)return_buffer-> - pointer)->type), - acpi_ut_get_type_name(return_type))); - - if (must_free) { - - /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ - - ACPI_FREE(return_buffer->pointer); - return_buffer->pointer = NULL; - } - - return_buffer->length = 0; - return_ACPI_STATUS(AE_TYPE); -} - -ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed) -#endif /* ACPI_FUTURE_USAGE */ -/******************************************************************************* - * - * FUNCTION: acpi_evaluate_object - * - * PARAMETERS: Handle - Object handle (optional) - * Pathname - Object pathname (optional) - * external_params - List of parameters to pass to method, - * terminated by NULL. May be NULL - * if no parameters are being passed. - * return_buffer - Where to put method's return value (if - * any). If NULL, no value is returned. - * - * RETURN: Status - * - * DESCRIPTION: Find and evaluate the given object, passing the given - * parameters if necessary. One of "Handle" or "Pathname" must - * be valid (non-null) - * - ******************************************************************************/ -acpi_status -acpi_evaluate_object(acpi_handle handle, - acpi_string pathname, - struct acpi_object_list *external_params, - struct acpi_buffer *return_buffer) -{ - acpi_status status; - struct acpi_evaluate_info *info; - acpi_size buffer_space_needed; - u32 i; - - ACPI_FUNCTION_TRACE(acpi_evaluate_object); - - /* Allocate and initialize the evaluation information block */ - - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); - if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - info->pathname = pathname; - - /* Convert and validate the device handle */ - - info->prefix_node = acpi_ns_map_handle_to_node(handle); - if (!info->prefix_node) { - status = AE_BAD_PARAMETER; - goto cleanup; - } - - /* - * If there are parameters to be passed to a control method, the external - * objects must all be converted to internal objects - */ - if (external_params && external_params->count) { - /* - * Allocate a new parameter block for the internal objects - * Add 1 to count to allow for null terminated internal list - */ - info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) - external_params-> - count + - 1) * sizeof(void *)); - if (!info->parameters) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Convert each external object in the list to an internal object */ - - for (i = 0; i < external_params->count; i++) { - status = - acpi_ut_copy_eobject_to_iobject(&external_params-> - pointer[i], - &info-> - parameters[i]); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - } - info->parameters[external_params->count] = NULL; - } - - /* - * Three major cases: - * 1) Fully qualified pathname - * 2) No handle, not fully qualified pathname (error) - * 3) Valid handle - */ - if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { - - /* The path is fully qualified, just evaluate by name */ - - info->prefix_node = NULL; - status = acpi_ns_evaluate(info); - } else if (!handle) { - /* - * A handle is optional iff a fully qualified pathname is specified. - * Since we've already handled fully qualified names above, this is - * an error - */ - if (!pathname) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Both Handle and Pathname are NULL")); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Null Handle with relative pathname [%s]", - pathname)); - } - - status = AE_BAD_PARAMETER; - } else { - /* We have a namespace a node and a possible relative path */ - - status = acpi_ns_evaluate(info); - } - - /* - * If we are expecting a return value, and all went well above, - * copy the return value to an external object. - */ - if (return_buffer) { - if (!info->return_object) { - return_buffer->length = 0; - } else { - if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) == - ACPI_DESC_TYPE_NAMED) { - /* - * If we received a NS Node as a return object, this means that - * the object we are evaluating has nothing interesting to - * return (such as a mutex, etc.) We return an error because - * these types are essentially unsupported by this interface. - * We don't check up front because this makes it easier to add - * support for various types at a later date if necessary. - */ - status = AE_TYPE; - info->return_object = NULL; /* No need to delete a NS Node */ - return_buffer->length = 0; - } - - if (ACPI_SUCCESS(status)) { - - /* Dereference Index and ref_of references */ - - acpi_ns_resolve_references(info); - - /* Get the size of the returned object */ - - status = - acpi_ut_get_object_size(info->return_object, - &buffer_space_needed); - if (ACPI_SUCCESS(status)) { - - /* Validate/Allocate/Clear caller buffer */ - - status = - acpi_ut_initialize_buffer - (return_buffer, - buffer_space_needed); - if (ACPI_FAILURE(status)) { - /* - * Caller's buffer is too small or a new one can't - * be allocated - */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Needed buffer size %X, %s\n", - (u32) - buffer_space_needed, - acpi_format_exception - (status))); - } else { - /* We have enough space for the object, build it */ - - status = - acpi_ut_copy_iobject_to_eobject - (info->return_object, - return_buffer); - } - } - } - } - } - - if (info->return_object) { - /* - * Delete the internal return object. NOTE: Interpreter must be - * locked to avoid race condition. - */ - acpi_ex_enter_interpreter(); - - /* Remove one reference on the return object (should delete it) */ - - acpi_ut_remove_reference(info->return_object); - acpi_ex_exit_interpreter(); - } - - cleanup: - - /* Free the input parameter list (if we created one) */ - - if (info->parameters) { - - /* Free the allocated parameter block */ - - acpi_ut_delete_internal_object_list(info->parameters); - } - - ACPI_FREE(info); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_evaluate_object) - -/******************************************************************************* - * - * FUNCTION: acpi_ns_resolve_references - * - * PARAMETERS: Info - Evaluation info block - * - * RETURN: Info->return_object is replaced with the dereferenced object - * - * DESCRIPTION: Dereference certain reference objects. Called before an - * internal return object is converted to an external union acpi_object. - * - * Performs an automatic dereference of Index and ref_of reference objects. - * These reference objects are not supported by the union acpi_object, so this is a - * last resort effort to return something useful. Also, provides compatibility - * with other ACPI implementations. - * - * NOTE: does not handle references within returned package objects or nested - * references, but this support could be added later if found to be necessary. - * - ******************************************************************************/ -static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) -{ - union acpi_operand_object *obj_desc = NULL; - struct acpi_namespace_node *node; - - /* We are interested in reference objects only */ - - if (ACPI_GET_OBJECT_TYPE(info->return_object) != - ACPI_TYPE_LOCAL_REFERENCE) { - return; - } - - /* - * Two types of references are supported - those created by Index and - * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted - * to an union acpi_object, so it is not dereferenced here. A ddb_handle - * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to - * an union acpi_object. - */ - switch (info->return_object->reference.class) { - case ACPI_REFCLASS_INDEX: - - obj_desc = *(info->return_object->reference.where); - break; - - case ACPI_REFCLASS_REFOF: - - node = info->return_object->reference.object; - if (node) { - obj_desc = node->object; - } - break; - - default: - return; - } - - /* Replace the existing reference object */ - - if (obj_desc) { - acpi_ut_add_reference(obj_desc); - acpi_ut_remove_reference(info->return_object); - info->return_object = obj_desc; - } - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_walk_namespace - * - * PARAMETERS: Type - acpi_object_type to search for - * start_object - Handle in namespace where search begins - * max_depth - Depth to which search is to reach - * user_function - Called when an object of "Type" is found - * Context - Passed to user function - * return_value - Location where return value of - * user_function is put if terminated early - * - * RETURNS Return value from the user_function if terminated early. - * Otherwise, returns NULL. - * - * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, - * starting (and ending) at the object specified by start_handle. - * The user_function is called whenever an object that matches - * the type parameter is found. If the user function returns - * a non-zero value, the search is terminated immediately and this - * value is returned to the caller. - * - * The point of this procedure is to provide a generic namespace - * walk routine that can be called from multiple places to - * provide multiple services; the User Function can be tailored - * to each task, whether it is a print function, a compare - * function, etc. - * - ******************************************************************************/ - -acpi_status -acpi_walk_namespace(acpi_object_type type, - acpi_handle start_object, - u32 max_depth, - acpi_walk_callback user_function, - void *context, void **return_value) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_walk_namespace); - - /* Parameter validation */ - - if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* - * Lock the namespace around the walk. - * The namespace will be unlocked/locked around each call - * to the user function - since this function - * must be allowed to make Acpi calls itself. - */ - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_ns_walk_namespace(type, start_object, max_depth, - ACPI_NS_WALK_UNLOCK, - user_function, context, return_value); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_walk_namespace) - -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_device_callback - * - * PARAMETERS: Callback from acpi_get_device - * - * RETURN: Status - * - * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non- - * present devices, or if they specified a HID, it filters based - * on that. - * - ******************************************************************************/ -static acpi_status -acpi_ns_get_device_callback(acpi_handle obj_handle, - u32 nesting_level, - void *context, void **return_value) -{ - struct acpi_get_devices_info *info = context; - acpi_status status; - struct acpi_namespace_node *node; - u32 flags; - struct acpica_device_id hid; - struct acpi_compatible_id_list *cid; - u32 i; - int found; - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - node = acpi_ns_map_handle_to_node(obj_handle); - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - if (!node) { - return (AE_BAD_PARAMETER); - } - - /* Run _STA to determine if device is present */ - - status = acpi_ut_execute_STA(node, &flags); - if (ACPI_FAILURE(status)) { - return (AE_CTRL_DEPTH); - } - - if (!(flags & ACPI_STA_DEVICE_PRESENT) && - !(flags & ACPI_STA_DEVICE_FUNCTIONING)) { - /* - * Don't examine the children of the device only when the - * device is neither present nor functional. See ACPI spec, - * description of _STA for more information. - */ - return (AE_CTRL_DEPTH); - } - - /* Filter based on device HID & CID */ - - if (info->hid != NULL) { - status = acpi_ut_execute_HID(node, &hid); - if (status == AE_NOT_FOUND) { - return (AE_OK); - } else if (ACPI_FAILURE(status)) { - return (AE_CTRL_DEPTH); - } - - if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) { - - /* Get the list of Compatible IDs */ - - status = acpi_ut_execute_CID(node, &cid); - if (status == AE_NOT_FOUND) { - return (AE_OK); - } else if (ACPI_FAILURE(status)) { - return (AE_CTRL_DEPTH); - } - - /* Walk the CID list */ - - found = 0; - for (i = 0; i < cid->count; i++) { - if (ACPI_STRNCMP(cid->id[i].value, info->hid, - sizeof(struct - acpi_compatible_id)) == - 0) { - found = 1; - break; - } - } - ACPI_FREE(cid); - if (!found) - return (AE_OK); - } - } - - status = info->user_function(obj_handle, nesting_level, info->context, - return_value); - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_get_devices - * - * PARAMETERS: HID - HID to search for. Can be NULL. - * user_function - Called when a matching object is found - * Context - Passed to user function - * return_value - Location where return value of - * user_function is put if terminated early - * - * RETURNS Return value from the user_function if terminated early. - * Otherwise, returns NULL. - * - * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, - * starting (and ending) at the object specified by start_handle. - * The user_function is called whenever an object of type - * Device is found. If the user function returns - * a non-zero value, the search is terminated immediately and this - * value is returned to the caller. - * - * This is a wrapper for walk_namespace, but the callback performs - * additional filtering. Please see acpi_ns_get_device_callback. - * - ******************************************************************************/ - -acpi_status -acpi_get_devices(const char *HID, - acpi_walk_callback user_function, - void *context, void **return_value) -{ - acpi_status status; - struct acpi_get_devices_info info; - - ACPI_FUNCTION_TRACE(acpi_get_devices); - - /* Parameter validation */ - - if (!user_function) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* - * We're going to call their callback from OUR callback, so we need - * to know what it is, and their context parameter. - */ - info.hid = HID; - info.context = context; - info.user_function = user_function; - - /* - * Lock the namespace around the walk. - * The namespace will be unlocked/locked around each call - * to the user function - since this function - * must be allowed to make Acpi calls itself. - */ - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, - acpi_ns_get_device_callback, &info, - return_value); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_devices) - -/******************************************************************************* - * - * FUNCTION: acpi_attach_data - * - * PARAMETERS: obj_handle - Namespace node - * Handler - Handler for this attachment - * Data - Pointer to data to be attached - * - * RETURN: Status - * - * DESCRIPTION: Attach arbitrary data and handler to a namespace node. - * - ******************************************************************************/ -acpi_status -acpi_attach_data(acpi_handle obj_handle, - acpi_object_handler handler, void *data) -{ - struct acpi_namespace_node *node; - acpi_status status; - - /* Parameter validation */ - - if (!obj_handle || !handler || !data) { - return (AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Convert and validate the handle */ - - node = acpi_ns_map_handle_to_node(obj_handle); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - status = acpi_ns_attach_data(node, handler, data); - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_attach_data) - -/******************************************************************************* - * - * FUNCTION: acpi_detach_data - * - * PARAMETERS: obj_handle - Namespace node handle - * Handler - Handler used in call to acpi_attach_data - * - * RETURN: Status - * - * DESCRIPTION: Remove data that was previously attached to a node. - * - ******************************************************************************/ -acpi_status -acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) -{ - struct acpi_namespace_node *node; - acpi_status status; - - /* Parameter validation */ - - if (!obj_handle || !handler) { - return (AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Convert and validate the handle */ - - node = acpi_ns_map_handle_to_node(obj_handle); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - status = acpi_ns_detach_data(node, handler); - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_detach_data) - -/******************************************************************************* - * - * FUNCTION: acpi_get_data - * - * PARAMETERS: obj_handle - Namespace node - * Handler - Handler used in call to attach_data - * Data - Where the data is returned - * - * RETURN: Status - * - * DESCRIPTION: Retrieve data that was previously attached to a namespace node. - * - ******************************************************************************/ -acpi_status -acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) -{ - struct acpi_namespace_node *node; - acpi_status status; - - /* Parameter validation */ - - if (!obj_handle || !handler || !data) { - return (AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Convert and validate the handle */ - - node = acpi_ns_map_handle_to_node(obj_handle); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - status = acpi_ns_get_attached_data(node, handler, data); - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_data) diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c deleted file mode 100644 index 7d5bfa9e9fe9..000000000000 --- a/drivers/acpi/namespace/nsxfname.c +++ /dev/null @@ -1,360 +0,0 @@ -/****************************************************************************** - * - * Module Name: nsxfname - Public interfaces to the ACPI subsystem - * ACPI Namespace oriented interfaces - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsxfname") - -/****************************************************************************** - * - * FUNCTION: acpi_get_handle - * - * PARAMETERS: Parent - Object to search under (search scope). - * Pathname - Pointer to an asciiz string containing the - * name - * ret_handle - Where the return handle is returned - * - * RETURN: Status - * - * DESCRIPTION: This routine will search for a caller specified name in the - * name space. The caller can restrict the search region by - * specifying a non NULL parent. The parent value is itself a - * namespace handle. - * - ******************************************************************************/ -acpi_status -acpi_get_handle(acpi_handle parent, - acpi_string pathname, acpi_handle * ret_handle) -{ - acpi_status status; - struct acpi_namespace_node *node = NULL; - struct acpi_namespace_node *prefix_node = NULL; - - ACPI_FUNCTION_ENTRY(); - - /* Parameter Validation */ - - if (!ret_handle || !pathname) { - return (AE_BAD_PARAMETER); - } - - /* Convert a parent handle to a prefix node */ - - if (parent) { - prefix_node = acpi_ns_map_handle_to_node(parent); - if (!prefix_node) { - return (AE_BAD_PARAMETER); - } - } - - /* - * Valid cases are: - * 1) Fully qualified pathname - * 2) Parent + Relative pathname - * - * Error for - */ - if (acpi_ns_valid_root_prefix(pathname[0])) { - - /* Pathname is fully qualified (starts with '\') */ - - /* Special case for root-only, since we can't search for it */ - - if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) { - *ret_handle = - acpi_ns_convert_entry_to_handle(acpi_gbl_root_node); - return (AE_OK); - } - } else if (!prefix_node) { - - /* Relative path with null prefix is disallowed */ - - return (AE_BAD_PARAMETER); - } - - /* Find the Node and convert to a handle */ - - status = - acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node); - if (ACPI_SUCCESS(status)) { - *ret_handle = acpi_ns_convert_entry_to_handle(node); - } - - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_handle) - -/****************************************************************************** - * - * FUNCTION: acpi_get_name - * - * PARAMETERS: Handle - Handle to be converted to a pathname - * name_type - Full pathname or single segment - * Buffer - Buffer for returned path - * - * RETURN: Pointer to a string containing the fully qualified Name. - * - * DESCRIPTION: This routine returns the fully qualified name associated with - * the Handle parameter. This and the acpi_pathname_to_handle are - * complementary functions. - * - ******************************************************************************/ -acpi_status -acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) -{ - acpi_status status; - struct acpi_namespace_node *node; - - /* Parameter validation */ - - if (name_type > ACPI_NAME_TYPE_MAX) { - return (AE_BAD_PARAMETER); - } - - status = acpi_ut_validate_buffer(buffer); - if (ACPI_FAILURE(status)) { - return (status); - } - - if (name_type == ACPI_FULL_PATHNAME) { - - /* Get the full pathname (From the namespace root) */ - - status = acpi_ns_handle_to_pathname(handle, buffer); - return (status); - } - - /* - * Wants the single segment ACPI name. - * Validate handle and convert to a namespace Node - */ - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - node = acpi_ns_map_handle_to_node(handle); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Validate/Allocate/Clear caller buffer */ - - status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - - /* Just copy the ACPI name from the Node and zero terminate it */ - - ACPI_STRNCPY(buffer->pointer, acpi_ut_get_node_name(node), - ACPI_NAME_SIZE); - ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0; - status = AE_OK; - - unlock_and_exit: - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_name) - -/****************************************************************************** - * - * FUNCTION: acpi_get_object_info - * - * PARAMETERS: Handle - Object Handle - * Buffer - Where the info is returned - * - * RETURN: Status - * - * DESCRIPTION: Returns information about an object as gleaned from the - * namespace node and possibly by running several standard - * control methods (Such as in the case of a device.) - * - ******************************************************************************/ -acpi_status -acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) -{ - acpi_status status; - struct acpi_namespace_node *node; - struct acpi_device_info *info; - struct acpi_device_info *return_info; - struct acpi_compatible_id_list *cid_list = NULL; - acpi_size size; - - /* Parameter validation */ - - if (!handle || !buffer) { - return (AE_BAD_PARAMETER); - } - - status = acpi_ut_validate_buffer(buffer); - if (ACPI_FAILURE(status)) { - return (status); - } - - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info)); - if (!info) { - return (AE_NO_MEMORY); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - node = acpi_ns_map_handle_to_node(handle); - if (!node) { - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - status = AE_BAD_PARAMETER; - goto cleanup; - } - - /* Init return structure */ - - size = sizeof(struct acpi_device_info); - - info->type = node->type; - info->name = node->name.integer; - info->valid = 0; - - if (node->type == ACPI_TYPE_METHOD) { - info->param_count = node->object->method.param_count; - } - - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* If not a device, we are all done */ - - if (info->type == ACPI_TYPE_DEVICE) { - /* - * Get extra info for ACPI Devices objects only: - * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods. - * - * Note: none of these methods are required, so they may or may - * not be present for this device. The Info->Valid bitfield is used - * to indicate which methods were found and ran successfully. - */ - - /* Execute the Device._HID method */ - - status = acpi_ut_execute_HID(node, &info->hardware_id); - if (ACPI_SUCCESS(status)) { - info->valid |= ACPI_VALID_HID; - } - - /* Execute the Device._UID method */ - - status = acpi_ut_execute_UID(node, &info->unique_id); - if (ACPI_SUCCESS(status)) { - info->valid |= ACPI_VALID_UID; - } - - /* Execute the Device._CID method */ - - status = acpi_ut_execute_CID(node, &cid_list); - if (ACPI_SUCCESS(status)) { - size += cid_list->size; - info->valid |= ACPI_VALID_CID; - } - - /* Execute the Device._STA method */ - - status = acpi_ut_execute_STA(node, &info->current_status); - if (ACPI_SUCCESS(status)) { - info->valid |= ACPI_VALID_STA; - } - - /* Execute the Device._ADR method */ - - status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node, - &info->address); - if (ACPI_SUCCESS(status)) { - info->valid |= ACPI_VALID_ADR; - } - - /* Execute the Device._sx_d methods */ - - status = acpi_ut_execute_sxds(node, info->highest_dstates); - if (ACPI_SUCCESS(status)) { - info->valid |= ACPI_VALID_SXDS; - } - } - - /* Validate/Allocate/Clear caller buffer */ - - status = acpi_ut_initialize_buffer(buffer, size); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Populate the return buffer */ - - return_info = buffer->pointer; - ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info)); - - if (cid_list) { - ACPI_MEMCPY(&return_info->compatibility_id, cid_list, - cid_list->size); - } - - cleanup: - ACPI_FREE(info); - if (cid_list) { - ACPI_FREE(cid_list); - } - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_object_info) diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c deleted file mode 100644 index 80e6322d59c5..000000000000 --- a/drivers/acpi/namespace/nsxfobj.c +++ /dev/null @@ -1,287 +0,0 @@ -/******************************************************************************* - * - * Module Name: nsxfobj - Public interfaces to the ACPI subsystem - * ACPI Object oriented interfaces - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsxfobj") - -/******************************************************************************* - * - * FUNCTION: acpi_get_id - * - * PARAMETERS: Handle - Handle of object whose id is desired - * ret_id - Where the id will be placed - * - * RETURN: Status - * - * DESCRIPTION: This routine returns the owner id associated with a handle - * - ******************************************************************************/ -acpi_status acpi_get_id(acpi_handle handle, acpi_owner_id * ret_id) -{ - struct acpi_namespace_node *node; - acpi_status status; - - /* Parameter Validation */ - - if (!ret_id) { - return (AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Convert and validate the handle */ - - node = acpi_ns_map_handle_to_node(handle); - if (!node) { - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (AE_BAD_PARAMETER); - } - - *ret_id = node->owner_id; - - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_id) - -/******************************************************************************* - * - * FUNCTION: acpi_get_type - * - * PARAMETERS: Handle - Handle of object whose type is desired - * ret_type - Where the type will be placed - * - * RETURN: Status - * - * DESCRIPTION: This routine returns the type associatd with a particular handle - * - ******************************************************************************/ -acpi_status acpi_get_type(acpi_handle handle, acpi_object_type * ret_type) -{ - struct acpi_namespace_node *node; - acpi_status status; - - /* Parameter Validation */ - - if (!ret_type) { - return (AE_BAD_PARAMETER); - } - - /* - * Special case for the predefined Root Node - * (return type ANY) - */ - if (handle == ACPI_ROOT_OBJECT) { - *ret_type = ACPI_TYPE_ANY; - return (AE_OK); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Convert and validate the handle */ - - node = acpi_ns_map_handle_to_node(handle); - if (!node) { - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (AE_BAD_PARAMETER); - } - - *ret_type = node->type; - - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_type) - -/******************************************************************************* - * - * FUNCTION: acpi_get_parent - * - * PARAMETERS: Handle - Handle of object whose parent is desired - * ret_handle - Where the parent handle will be placed - * - * RETURN: Status - * - * DESCRIPTION: Returns a handle to the parent of the object represented by - * Handle. - * - ******************************************************************************/ -acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle) -{ - struct acpi_namespace_node *node; - acpi_status status; - - if (!ret_handle) { - return (AE_BAD_PARAMETER); - } - - /* Special case for the predefined Root Node (no parent) */ - - if (handle == ACPI_ROOT_OBJECT) { - return (AE_NULL_ENTRY); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Convert and validate the handle */ - - node = acpi_ns_map_handle_to_node(handle); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* Get the parent entry */ - - *ret_handle = - acpi_ns_convert_entry_to_handle(acpi_ns_get_parent_node(node)); - - /* Return exception if parent is null */ - - if (!acpi_ns_get_parent_node(node)) { - status = AE_NULL_ENTRY; - } - - unlock_and_exit: - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_parent) - -/******************************************************************************* - * - * FUNCTION: acpi_get_next_object - * - * PARAMETERS: Type - Type of object to be searched for - * Parent - Parent object whose children we are getting - * last_child - Previous child that was found. - * The NEXT child will be returned - * ret_handle - Where handle to the next object is placed - * - * RETURN: Status - * - * DESCRIPTION: Return the next peer object within the namespace. If Handle is - * valid, Scope is ignored. Otherwise, the first object within - * Scope is returned. - * - ******************************************************************************/ -acpi_status -acpi_get_next_object(acpi_object_type type, - acpi_handle parent, - acpi_handle child, acpi_handle * ret_handle) -{ - acpi_status status; - struct acpi_namespace_node *node; - struct acpi_namespace_node *parent_node = NULL; - struct acpi_namespace_node *child_node = NULL; - - /* Parameter validation */ - - if (type > ACPI_TYPE_EXTERNAL_MAX) { - return (AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* If null handle, use the parent */ - - if (!child) { - - /* Start search at the beginning of the specified scope */ - - parent_node = acpi_ns_map_handle_to_node(parent); - if (!parent_node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - } else { - /* Non-null handle, ignore the parent */ - /* Convert and validate the handle */ - - child_node = acpi_ns_map_handle_to_node(child); - if (!child_node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - } - - /* Internal function does the real work */ - - node = acpi_ns_get_next_node(type, parent_node, child_node); - if (!node) { - status = AE_NOT_FOUND; - goto unlock_and_exit; - } - - if (ret_handle) { - *ret_handle = acpi_ns_convert_entry_to_handle(node); - } - - unlock_and_exit: - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_next_object) diff --git a/drivers/acpi/parser/Makefile b/drivers/acpi/parser/Makefile deleted file mode 100644 index db24ee09cf11..000000000000 --- a/drivers/acpi/parser/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -obj-y := psargs.o psparse.o psloop.o pstree.o pswalk.o \ - psopcode.o psscope.o psutils.o psxface.o - -EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c deleted file mode 100644 index 852f3a83b2e6..000000000000 --- a/drivers/acpi/parser/psargs.c +++ /dev/null @@ -1,752 +0,0 @@ -/****************************************************************************** - * - * Module Name: psargs - Parse AML opcode arguments - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_PARSER -ACPI_MODULE_NAME("psargs") - -/* Local prototypes */ -static u32 -acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state); - -static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state - *parser_state); - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_next_package_length - * - * PARAMETERS: parser_state - Current parser state object - * - * RETURN: Decoded package length. On completion, the AML pointer points - * past the length byte or bytes. - * - * DESCRIPTION: Decode and return a package length field. - * Note: Largest package length is 28 bits, from ACPI specification - * - ******************************************************************************/ - -static u32 -acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) -{ - u8 *aml = parser_state->aml; - u32 package_length = 0; - u32 byte_count; - u8 byte_zero_mask = 0x3F; /* Default [0:5] */ - - ACPI_FUNCTION_TRACE(ps_get_next_package_length); - - /* - * Byte 0 bits [6:7] contain the number of additional bytes - * used to encode the package length, either 0,1,2, or 3 - */ - byte_count = (aml[0] >> 6); - parser_state->aml += ((acpi_size) byte_count + 1); - - /* Get bytes 3, 2, 1 as needed */ - - while (byte_count) { - /* - * Final bit positions for the package length bytes: - * Byte3->[20:27] - * Byte2->[12:19] - * Byte1->[04:11] - * Byte0->[00:03] - */ - package_length |= (aml[byte_count] << ((byte_count << 3) - 4)); - - byte_zero_mask = 0x0F; /* Use bits [0:3] of byte 0 */ - byte_count--; - } - - /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */ - - package_length |= (aml[0] & byte_zero_mask); - return_UINT32(package_length); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_next_package_end - * - * PARAMETERS: parser_state - Current parser state object - * - * RETURN: Pointer to end-of-package +1 - * - * DESCRIPTION: Get next package length and return a pointer past the end of - * the package. Consumes the package length field - * - ******************************************************************************/ - -u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state) -{ - u8 *start = parser_state->aml; - u32 package_length; - - ACPI_FUNCTION_TRACE(ps_get_next_package_end); - - /* Function below updates parser_state->Aml */ - - package_length = acpi_ps_get_next_package_length(parser_state); - - return_PTR(start + package_length); /* end of package */ -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_next_namestring - * - * PARAMETERS: parser_state - Current parser state object - * - * RETURN: Pointer to the start of the name string (pointer points into - * the AML. - * - * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name - * prefix characters. Set parser state to point past the string. - * (Name is consumed from the AML.) - * - ******************************************************************************/ - -char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) -{ - u8 *start = parser_state->aml; - u8 *end = parser_state->aml; - - ACPI_FUNCTION_TRACE(ps_get_next_namestring); - - /* Point past any namestring prefix characters (backslash or carat) */ - - while (acpi_ps_is_prefix_char(*end)) { - end++; - } - - /* Decode the path prefix character */ - - switch (*end) { - case 0: - - /* null_name */ - - if (end == start) { - start = NULL; - } - end++; - break; - - case AML_DUAL_NAME_PREFIX: - - /* Two name segments */ - - end += 1 + (2 * ACPI_NAME_SIZE); - break; - - case AML_MULTI_NAME_PREFIX_OP: - - /* Multiple name segments, 4 chars each, count in next byte */ - - end += 2 + (*(end + 1) * ACPI_NAME_SIZE); - break; - - default: - - /* Single name segment */ - - end += ACPI_NAME_SIZE; - break; - } - - parser_state->aml = end; - return_PTR((char *)start); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_next_namepath - * - * PARAMETERS: parser_state - Current parser state object - * Arg - Where the namepath will be stored - * arg_count - If the namepath points to a control method - * the method's argument is returned here. - * possible_method_call - Whether the namepath can possibly be the - * start of a method call - * - * RETURN: Status - * - * DESCRIPTION: Get next name (if method call, return # of required args). - * Names are looked up in the internal namespace to determine - * if the name represents a control method. If a method - * is found, the number of arguments to the method is returned. - * This information is critical for parsing to continue correctly. - * - ******************************************************************************/ - -acpi_status -acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, - struct acpi_parse_state *parser_state, - union acpi_parse_object *arg, u8 possible_method_call) -{ - acpi_status status; - char *path; - union acpi_parse_object *name_op; - union acpi_operand_object *method_desc; - struct acpi_namespace_node *node; - u8 *start = parser_state->aml; - - ACPI_FUNCTION_TRACE(ps_get_next_namepath); - - path = acpi_ps_get_next_namestring(parser_state); - acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); - - /* Null path case is allowed, just exit */ - - if (!path) { - arg->common.value.name = path; - return_ACPI_STATUS(AE_OK); - } - - /* - * Lookup the name in the internal namespace, starting with the current - * scope. We don't want to add anything new to the namespace here, - * however, so we use MODE_EXECUTE. - * Allow searching of the parent tree, but don't open a new scope - - * we just want to lookup the object (must be mode EXECUTE to perform - * the upsearch) - */ - status = acpi_ns_lookup(walk_state->scope_info, path, - ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, - NULL, &node); - - /* - * If this name is a control method invocation, we must - * setup the method call - */ - if (ACPI_SUCCESS(status) && - possible_method_call && (node->type == ACPI_TYPE_METHOD)) { - if (walk_state->opcode == AML_UNLOAD_OP) { - /* - * acpi_ps_get_next_namestring has increased the AML pointer, - * so we need to restore the saved AML pointer for method call. - */ - walk_state->parser_state.aml = start; - walk_state->arg_count = 1; - acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); - return_ACPI_STATUS(AE_OK); - } - - /* This name is actually a control method invocation */ - - method_desc = acpi_ns_get_attached_object(node); - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Control Method - %p Desc %p Path=%p\n", node, - method_desc, path)); - - name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); - if (!name_op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Change Arg into a METHOD CALL and attach name to it */ - - acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); - name_op->common.value.name = path; - - /* Point METHODCALL/NAME to the METHOD Node */ - - name_op->common.node = node; - acpi_ps_append_arg(arg, name_op); - - if (!method_desc) { - ACPI_ERROR((AE_INFO, - "Control Method %p has no attached object", - node)); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Control Method - %p Args %X\n", - node, method_desc->method.param_count)); - - /* Get the number of arguments to expect */ - - walk_state->arg_count = method_desc->method.param_count; - return_ACPI_STATUS(AE_OK); - } - - /* - * Special handling if the name was not found during the lookup - - * some not_found cases are allowed - */ - if (status == AE_NOT_FOUND) { - - /* 1) not_found is ok during load pass 1/2 (allow forward references) */ - - if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) != - ACPI_PARSE_EXECUTE) { - status = AE_OK; - } - - /* 2) not_found during a cond_ref_of(x) is ok by definition */ - - else if (walk_state->op->common.aml_opcode == - AML_COND_REF_OF_OP) { - status = AE_OK; - } - - /* - * 3) not_found while building a Package is ok at this point, we - * may flag as an error later if slack mode is not enabled. - * (Some ASL code depends on allowing this behavior) - */ - else if ((arg->common.parent) && - ((arg->common.parent->common.aml_opcode == - AML_PACKAGE_OP) - || (arg->common.parent->common.aml_opcode == - AML_VAR_PACKAGE_OP))) { - status = AE_OK; - } - } - - /* Final exception check (may have been changed from code above) */ - - if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(path, status); - - if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == - ACPI_PARSE_EXECUTE) { - - /* Report a control method execution error */ - - status = acpi_ds_method_error(status, walk_state); - } - } - - /* Save the namepath */ - - arg->common.value.name = path; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_next_simple_arg - * - * PARAMETERS: parser_state - Current parser state object - * arg_type - The argument type (AML_*_ARG) - * Arg - Where the argument is returned - * - * RETURN: None - * - * DESCRIPTION: Get the next simple argument (constant, string, or namestring) - * - ******************************************************************************/ - -void -acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, - u32 arg_type, union acpi_parse_object *arg) -{ - u32 length; - u16 opcode; - u8 *aml = parser_state->aml; - - ACPI_FUNCTION_TRACE_U32(ps_get_next_simple_arg, arg_type); - - switch (arg_type) { - case ARGP_BYTEDATA: - - /* Get 1 byte from the AML stream */ - - opcode = AML_BYTE_OP; - arg->common.value.integer = (acpi_integer) * aml; - length = 1; - break; - - case ARGP_WORDDATA: - - /* Get 2 bytes from the AML stream */ - - opcode = AML_WORD_OP; - ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml); - length = 2; - break; - - case ARGP_DWORDDATA: - - /* Get 4 bytes from the AML stream */ - - opcode = AML_DWORD_OP; - ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml); - length = 4; - break; - - case ARGP_QWORDDATA: - - /* Get 8 bytes from the AML stream */ - - opcode = AML_QWORD_OP; - ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml); - length = 8; - break; - - case ARGP_CHARLIST: - - /* Get a pointer to the string, point past the string */ - - opcode = AML_STRING_OP; - arg->common.value.string = ACPI_CAST_PTR(char, aml); - - /* Find the null terminator */ - - length = 0; - while (aml[length]) { - length++; - } - length++; - break; - - case ARGP_NAME: - case ARGP_NAMESTRING: - - acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); - arg->common.value.name = - acpi_ps_get_next_namestring(parser_state); - return_VOID; - - default: - - ACPI_ERROR((AE_INFO, "Invalid ArgType %X", arg_type)); - return_VOID; - } - - acpi_ps_init_op(arg, opcode); - parser_state->aml += length; - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_next_field - * - * PARAMETERS: parser_state - Current parser state object - * - * RETURN: A newly allocated FIELD op - * - * DESCRIPTION: Get next field (named_field, reserved_field, or access_field) - * - ******************************************************************************/ - -static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state - *parser_state) -{ - u32 aml_offset = (u32) - ACPI_PTR_DIFF(parser_state->aml, - parser_state->aml_start); - union acpi_parse_object *field; - u16 opcode; - u32 name; - - ACPI_FUNCTION_TRACE(ps_get_next_field); - - /* Determine field type */ - - switch (ACPI_GET8(parser_state->aml)) { - default: - - opcode = AML_INT_NAMEDFIELD_OP; - break; - - case 0x00: - - opcode = AML_INT_RESERVEDFIELD_OP; - parser_state->aml++; - break; - - case 0x01: - - opcode = AML_INT_ACCESSFIELD_OP; - parser_state->aml++; - break; - } - - /* Allocate a new field op */ - - field = acpi_ps_alloc_op(opcode); - if (!field) { - return_PTR(NULL); - } - - field->common.aml_offset = aml_offset; - - /* Decode the field type */ - - switch (opcode) { - case AML_INT_NAMEDFIELD_OP: - - /* Get the 4-character name */ - - ACPI_MOVE_32_TO_32(&name, parser_state->aml); - acpi_ps_set_name(field, name); - parser_state->aml += ACPI_NAME_SIZE; - - /* Get the length which is encoded as a package length */ - - field->common.value.size = - acpi_ps_get_next_package_length(parser_state); - break; - - case AML_INT_RESERVEDFIELD_OP: - - /* Get the length which is encoded as a package length */ - - field->common.value.size = - acpi_ps_get_next_package_length(parser_state); - break; - - case AML_INT_ACCESSFIELD_OP: - - /* - * Get access_type and access_attrib and merge into the field Op - * access_type is first operand, access_attribute is second - */ - field->common.value.integer = - (((u32) ACPI_GET8(parser_state->aml) << 8)); - parser_state->aml++; - field->common.value.integer |= ACPI_GET8(parser_state->aml); - parser_state->aml++; - break; - - default: - - /* Opcode was set in previous switch */ - break; - } - - return_PTR(field); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_next_arg - * - * PARAMETERS: walk_state - Current state - * parser_state - Current parser state object - * arg_type - The argument type (AML_*_ARG) - * return_arg - Where the next arg is returned - * - * RETURN: Status, and an op object containing the next argument. - * - * DESCRIPTION: Get next argument (including complex list arguments that require - * pushing the parser stack) - * - ******************************************************************************/ - -acpi_status -acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, - struct acpi_parse_state *parser_state, - u32 arg_type, union acpi_parse_object **return_arg) -{ - union acpi_parse_object *arg = NULL; - union acpi_parse_object *prev = NULL; - union acpi_parse_object *field; - u32 subop; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_PTR(ps_get_next_arg, parser_state); - - switch (arg_type) { - case ARGP_BYTEDATA: - case ARGP_WORDDATA: - case ARGP_DWORDDATA: - case ARGP_CHARLIST: - case ARGP_NAME: - case ARGP_NAMESTRING: - - /* Constants, strings, and namestrings are all the same size */ - - arg = acpi_ps_alloc_op(AML_BYTE_OP); - if (!arg) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - acpi_ps_get_next_simple_arg(parser_state, arg_type, arg); - break; - - case ARGP_PKGLENGTH: - - /* Package length, nothing returned */ - - parser_state->pkg_end = - acpi_ps_get_next_package_end(parser_state); - break; - - case ARGP_FIELDLIST: - - if (parser_state->aml < parser_state->pkg_end) { - - /* Non-empty list */ - - while (parser_state->aml < parser_state->pkg_end) { - field = acpi_ps_get_next_field(parser_state); - if (!field) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - if (prev) { - prev->common.next = field; - } else { - arg = field; - } - prev = field; - } - - /* Skip to End of byte data */ - - parser_state->aml = parser_state->pkg_end; - } - break; - - case ARGP_BYTELIST: - - if (parser_state->aml < parser_state->pkg_end) { - - /* Non-empty list */ - - arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP); - if (!arg) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Fill in bytelist data */ - - arg->common.value.size = (u32) - ACPI_PTR_DIFF(parser_state->pkg_end, - parser_state->aml); - arg->named.data = parser_state->aml; - - /* Skip to End of byte data */ - - parser_state->aml = parser_state->pkg_end; - } - break; - - case ARGP_TARGET: - case ARGP_SUPERNAME: - case ARGP_SIMPLENAME: - - subop = acpi_ps_peek_opcode(parser_state); - if (subop == 0 || - acpi_ps_is_leading_char(subop) || - acpi_ps_is_prefix_char(subop)) { - - /* null_name or name_string */ - - arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); - if (!arg) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* To support super_name arg of Unload */ - - if (walk_state->opcode == AML_UNLOAD_OP) { - status = - acpi_ps_get_next_namepath(walk_state, - parser_state, arg, - 1); - - /* - * If the super_name arg of Unload is a method call, - * we have restored the AML pointer, just free this Arg - */ - if (arg->common.aml_opcode == - AML_INT_METHODCALL_OP) { - acpi_ps_free_op(arg); - arg = NULL; - } - } else { - status = - acpi_ps_get_next_namepath(walk_state, - parser_state, arg, - 0); - } - } else { - /* Single complex argument, nothing returned */ - - walk_state->arg_count = 1; - } - break; - - case ARGP_DATAOBJ: - case ARGP_TERMARG: - - /* Single complex argument, nothing returned */ - - walk_state->arg_count = 1; - break; - - case ARGP_DATAOBJLIST: - case ARGP_TERMLIST: - case ARGP_OBJLIST: - - if (parser_state->aml < parser_state->pkg_end) { - - /* Non-empty list of variable arguments, nothing returned */ - - walk_state->arg_count = ACPI_VAR_ARGS; - } - break; - - default: - - ACPI_ERROR((AE_INFO, "Invalid ArgType: %X", arg_type)); - status = AE_AML_OPERAND_TYPE; - break; - } - - *return_arg = arg; - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c deleted file mode 100644 index fd6648f0d65f..000000000000 --- a/drivers/acpi/parser/psloop.c +++ /dev/null @@ -1,1088 +0,0 @@ -/****************************************************************************** - * - * Module Name: psloop - Main AML parse loop - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -/* - * Parse the AML and build an operation tree as most interpreters, (such as - * Perl) do. Parsing is done by hand rather than with a YACC generated parser - * to tightly constrain stack and dynamic memory usage. Parsing is kept - * flexible and the code fairly compact by parsing based on a list of AML - * opcode templates in aml_op_info[]. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_PARSER -ACPI_MODULE_NAME("psloop") - -static u32 acpi_gbl_depth = 0; - -/* Local prototypes */ - -static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state); - -static acpi_status -acpi_ps_build_named_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, - union acpi_parse_object *unnamed_op, - union acpi_parse_object **op); - -static acpi_status -acpi_ps_create_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object **new_op); - -static acpi_status -acpi_ps_get_arguments(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object *op); - -static acpi_status -acpi_ps_complete_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **op, acpi_status status); - -static acpi_status -acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, acpi_status status); - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_aml_opcode - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Extract the next AML opcode from the input stream. - * - ******************************************************************************/ - -static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) -{ - - ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); - - walk_state->aml_offset = - (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, - walk_state->parser_state.aml_start); - walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); - - /* - * First cut to determine what we have found: - * 1) A valid AML opcode - * 2) A name string - * 3) An unknown/invalid opcode - */ - walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); - - switch (walk_state->op_info->class) { - case AML_CLASS_ASCII: - case AML_CLASS_PREFIX: - /* - * Starts with a valid prefix or ASCII char, this is a name - * string. Convert the bare name string to a namepath. - */ - walk_state->opcode = AML_INT_NAMEPATH_OP; - walk_state->arg_types = ARGP_NAMESTRING; - break; - - case AML_CLASS_UNKNOWN: - - /* The opcode is unrecognized. Just skip unknown opcodes */ - - ACPI_ERROR((AE_INFO, - "Found unknown opcode %X at AML address %p offset %X, ignoring", - walk_state->opcode, walk_state->parser_state.aml, - walk_state->aml_offset)); - - ACPI_DUMP_BUFFER(walk_state->parser_state.aml, 128); - - /* Assume one-byte bad opcode */ - - walk_state->parser_state.aml++; - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - - default: - - /* Found opcode info, this is a normal opcode */ - - walk_state->parser_state.aml += - acpi_ps_get_opcode_size(walk_state->opcode); - walk_state->arg_types = walk_state->op_info->parse_args; - break; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_build_named_op - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Begin of named Op in AML - * unnamed_op - Early Op (not a named Op) - * Op - Returned Op - * - * RETURN: Status - * - * DESCRIPTION: Parse a named Op - * - ******************************************************************************/ - -static acpi_status -acpi_ps_build_named_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, - union acpi_parse_object *unnamed_op, - union acpi_parse_object **op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *arg = NULL; - - ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); - - unnamed_op->common.value.arg = NULL; - unnamed_op->common.arg_list_length = 0; - unnamed_op->common.aml_opcode = walk_state->opcode; - - /* - * Get and append arguments until we find the node that contains - * the name (the type ARGP_NAME). - */ - while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && - (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) { - status = - acpi_ps_get_next_arg(walk_state, - &(walk_state->parser_state), - GET_CURRENT_ARG_TYPE(walk_state-> - arg_types), &arg); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - acpi_ps_append_arg(unnamed_op, arg); - INCREMENT_ARG_LIST(walk_state->arg_types); - } - - /* - * Make sure that we found a NAME and didn't run out of arguments - */ - if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) { - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - /* We know that this arg is a name, move to next arg */ - - INCREMENT_ARG_LIST(walk_state->arg_types); - - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = NULL; - - status = walk_state->descending_callback(walk_state, op); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); - return_ACPI_STATUS(status); - } - - if (!*op) { - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - } - - status = acpi_ps_next_parse_state(walk_state, *op, status); - if (ACPI_FAILURE(status)) { - if (status == AE_CTRL_PENDING) { - return_ACPI_STATUS(AE_CTRL_PARSE_PENDING); - } - return_ACPI_STATUS(status); - } - - acpi_ps_append_arg(*op, unnamed_op->common.value.arg); - acpi_gbl_depth++; - - if ((*op)->common.aml_opcode == AML_REGION_OP || - (*op)->common.aml_opcode == AML_DATA_REGION_OP) { - /* - * Defer final parsing of an operation_region body, because we don't - * have enough info in the first pass to parse it correctly (i.e., - * there may be method calls within the term_arg elements of the body.) - * - * However, we must continue parsing because the opregion is not a - * standalone package -- we don't know where the end is at this point. - * - * (Length is unknown until parse of the body complete) - */ - (*op)->named.data = aml_op_start; - (*op)->named.length = 0; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_create_op - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Op start in AML - * new_op - Returned Op - * - * RETURN: Status - * - * DESCRIPTION: Get Op from AML - * - ******************************************************************************/ - -static acpi_status -acpi_ps_create_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object **new_op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *op; - union acpi_parse_object *named_op = NULL; - union acpi_parse_object *parent_scope; - u8 argument_count; - const struct acpi_opcode_info *op_info; - - ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); - - status = acpi_ps_get_aml_opcode(walk_state); - if (status == AE_CTRL_PARSE_CONTINUE) { - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - } - - /* Create Op structure and append to parent's argument list */ - - walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); - op = acpi_ps_alloc_op(walk_state->opcode); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - if (walk_state->op_info->flags & AML_NAMED) { - status = - acpi_ps_build_named_op(walk_state, aml_op_start, op, - &named_op); - acpi_ps_free_op(op); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - *new_op = named_op; - return_ACPI_STATUS(AE_OK); - } - - /* Not a named opcode, just allocate Op and append to parent */ - - if (walk_state->op_info->flags & AML_CREATE) { - /* - * Backup to beginning of create_xXXfield declaration - * body_length is unknown until we parse the body - */ - op->named.data = aml_op_start; - op->named.length = 0; - } - - if (walk_state->opcode == AML_BANK_FIELD_OP) { - /* - * Backup to beginning of bank_field declaration - * body_length is unknown until we parse the body - */ - op->named.data = aml_op_start; - op->named.length = 0; - } - - parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); - acpi_ps_append_arg(parent_scope, op); - - if (parent_scope) { - op_info = - acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); - if (op_info->flags & AML_HAS_TARGET) { - argument_count = - acpi_ps_get_argument_count(op_info->type); - if (parent_scope->common.arg_list_length > - argument_count) { - op->common.flags |= ACPI_PARSEOP_TARGET; - } - } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { - op->common.flags |= ACPI_PARSEOP_TARGET; - } - } - - if (walk_state->descending_callback != NULL) { - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = *new_op = op; - - status = walk_state->descending_callback(walk_state, &op); - status = acpi_ps_next_parse_state(walk_state, op, status); - if (status == AE_CTRL_PENDING) { - status = AE_CTRL_PARSE_PENDING; - } - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_arguments - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Op start in AML - * Op - Current Op - * - * RETURN: Status - * - * DESCRIPTION: Get arguments for passed Op. - * - ******************************************************************************/ - -static acpi_status -acpi_ps_get_arguments(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object *op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *arg = NULL; - - ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state); - - switch (op->common.aml_opcode) { - case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ - case AML_WORD_OP: /* AML_WORDDATA_ARG */ - case AML_DWORD_OP: /* AML_DWORDATA_ARG */ - case AML_QWORD_OP: /* AML_QWORDATA_ARG */ - case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ - - /* Fill in constant or string argument directly */ - - acpi_ps_get_next_simple_arg(&(walk_state->parser_state), - GET_CURRENT_ARG_TYPE(walk_state-> - arg_types), - op); - break; - - case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ - - status = - acpi_ps_get_next_namepath(walk_state, - &(walk_state->parser_state), op, - 1); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - walk_state->arg_types = 0; - break; - - default: - /* - * Op is not a constant or string, append each argument to the Op - */ - while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) - && !walk_state->arg_count) { - walk_state->aml_offset = - (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, - walk_state->parser_state. - aml_start); - - status = - acpi_ps_get_next_arg(walk_state, - &(walk_state->parser_state), - GET_CURRENT_ARG_TYPE - (walk_state->arg_types), &arg); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (arg) { - arg->common.aml_offset = walk_state->aml_offset; - acpi_ps_append_arg(op, arg); - } - - INCREMENT_ARG_LIST(walk_state->arg_types); - } - - /* Special processing for certain opcodes */ - - /* TBD (remove): Temporary mechanism to disable this code if needed */ - -#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE - - if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) && - ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { - /* - * We want to skip If/Else/While constructs during Pass1 because we - * want to actually conditionally execute the code during Pass2. - * - * Except for disassembly, where we always want to walk the - * If/Else/While packages - */ - switch (op->common.aml_opcode) { - case AML_IF_OP: - case AML_ELSE_OP: - case AML_WHILE_OP: - - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Pass1: Skipping an If/Else/While body\n")); - - /* Skip body of if/else/while in pass 1 */ - - walk_state->parser_state.aml = - walk_state->parser_state.pkg_end; - walk_state->arg_count = 0; - break; - - default: - break; - } - } -#endif - - switch (op->common.aml_opcode) { - case AML_METHOD_OP: - /* - * Skip parsing of control method because we don't have enough - * info in the first pass to parse it correctly. - * - * Save the length and address of the body - */ - op->named.data = walk_state->parser_state.aml; - op->named.length = (u32) - (walk_state->parser_state.pkg_end - - walk_state->parser_state.aml); - - /* Skip body of method */ - - walk_state->parser_state.aml = - walk_state->parser_state.pkg_end; - walk_state->arg_count = 0; - break; - - case AML_BUFFER_OP: - case AML_PACKAGE_OP: - case AML_VAR_PACKAGE_OP: - - if ((op->common.parent) && - (op->common.parent->common.aml_opcode == - AML_NAME_OP) - && (walk_state->pass_number <= - ACPI_IMODE_LOAD_PASS2)) { - /* - * Skip parsing of Buffers and Packages because we don't have - * enough info in the first pass to parse them correctly. - */ - op->named.data = aml_op_start; - op->named.length = (u32) - (walk_state->parser_state.pkg_end - - aml_op_start); - - /* Skip body */ - - walk_state->parser_state.aml = - walk_state->parser_state.pkg_end; - walk_state->arg_count = 0; - } - break; - - case AML_WHILE_OP: - - if (walk_state->control_state) { - walk_state->control_state->control.package_end = - walk_state->parser_state.pkg_end; - } - break; - - default: - - /* No action for all other opcodes */ - break; - } - - break; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_complete_op - * - * PARAMETERS: walk_state - Current state - * Op - Returned Op - * Status - Parse status before complete Op - * - * RETURN: Status - * - * DESCRIPTION: Complete Op - * - ******************************************************************************/ - -static acpi_status -acpi_ps_complete_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **op, acpi_status status) -{ - acpi_status status2; - - ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); - - /* - * Finished one argument of the containing scope - */ - walk_state->parser_state.scope->parse_scope.arg_count--; - - /* Close this Op (will result in parse subtree deletion) */ - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - *op = NULL; - - switch (status) { - case AE_OK: - break; - - case AE_CTRL_TRANSFER: - - /* We are about to transfer to a called method */ - - walk_state->prev_op = NULL; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS(status); - - case AE_CTRL_END: - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - if (*op) { - walk_state->op = *op; - walk_state->op_info = - acpi_ps_get_opcode_info((*op)->common.aml_opcode); - walk_state->opcode = (*op)->common.aml_opcode; - - status = walk_state->ascending_callback(walk_state); - status = - acpi_ps_next_parse_state(walk_state, *op, status); - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - status = AE_OK; - break; - - case AE_CTRL_BREAK: - case AE_CTRL_CONTINUE: - - /* Pop off scopes until we find the While */ - - while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - } - - /* Close this iteration of the While loop */ - - walk_state->op = *op; - walk_state->op_info = - acpi_ps_get_opcode_info((*op)->common.aml_opcode); - walk_state->opcode = (*op)->common.aml_opcode; - - status = walk_state->ascending_callback(walk_state); - status = acpi_ps_next_parse_state(walk_state, *op, status); - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - status = AE_OK; - break; - - case AE_CTRL_TERMINATE: - - /* Clean up */ - do { - if (*op) { - status2 = - acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - acpi_ut_delete_generic_state - (acpi_ut_pop_generic_state - (&walk_state->control_state)); - } - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (*op); - - return_ACPI_STATUS(AE_OK); - - default: /* All other non-AE_OK status */ - - do { - if (*op) { - status2 = - acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (*op); - -#if 0 - /* - * TBD: Cleanup parse ops on error - */ - if (*op == NULL) { - acpi_ps_pop_scope(parser_state, op, - &walk_state->arg_types, - &walk_state->arg_count); - } -#endif - walk_state->prev_op = NULL; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS(status); - } - - /* This scope complete? */ - - if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); - } else { - *op = NULL; - } - - ACPI_PREEMPTION_POINT(); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_complete_final_op - * - * PARAMETERS: walk_state - Current state - * Op - Current Op - * Status - Current parse status before complete last - * Op - * - * RETURN: Status - * - * DESCRIPTION: Complete last Op. - * - ******************************************************************************/ - -static acpi_status -acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, acpi_status status) -{ - acpi_status status2; - - ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); - - /* - * Complete the last Op (if not completed), and clear the scope stack. - * It is easily possible to end an AML "package" with an unbounded number - * of open scopes (such as when several ASL blocks are closed with - * sequential closing braces). We want to terminate each one cleanly. - */ - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", - op)); - do { - if (op) { - if (walk_state->ascending_callback != NULL) { - walk_state->op = op; - walk_state->op_info = - acpi_ps_get_opcode_info(op->common. - aml_opcode); - walk_state->opcode = op->common.aml_opcode; - - status = - walk_state->ascending_callback(walk_state); - status = - acpi_ps_next_parse_state(walk_state, op, - status); - if (status == AE_CTRL_PENDING) { - status = - acpi_ps_complete_op(walk_state, &op, - AE_OK); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - if (status == AE_CTRL_TERMINATE) { - status = AE_OK; - - /* Clean up */ - do { - if (op) { - status2 = - acpi_ps_complete_this_op - (walk_state, op); - if (ACPI_FAILURE - (status2)) { - return_ACPI_STATUS - (status2); - } - } - - acpi_ps_pop_scope(& - (walk_state-> - parser_state), - &op, - &walk_state-> - arg_types, - &walk_state-> - arg_count); - - } while (op); - - return_ACPI_STATUS(status); - } - - else if (ACPI_FAILURE(status)) { - - /* First error is most important */ - - (void) - acpi_ps_complete_this_op(walk_state, - op); - return_ACPI_STATUS(status); - } - } - - status2 = acpi_ps_complete_this_op(walk_state, op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - acpi_ps_pop_scope(&(walk_state->parser_state), &op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (op); - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_parse_loop - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Parse AML (pointed to by the current parser state) and return - * a tree of ops. - * - ******************************************************************************/ - -acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - union acpi_parse_object *op = NULL; /* current op */ - struct acpi_parse_state *parser_state; - u8 *aml_op_start = NULL; - - ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state); - - if (walk_state->descending_callback == NULL) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - parser_state = &walk_state->parser_state; - walk_state->arg_types = 0; - -#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) - - if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { - - /* We are restarting a preempted control method */ - - if (acpi_ps_has_completed_scope(parser_state)) { - /* - * We must check if a predicate to an IF or WHILE statement - * was just completed - */ - if ((parser_state->scope->parse_scope.op) && - ((parser_state->scope->parse_scope.op->common. - aml_opcode == AML_IF_OP) - || (parser_state->scope->parse_scope.op->common. - aml_opcode == AML_WHILE_OP)) - && (walk_state->control_state) - && (walk_state->control_state->common.state == - ACPI_CONTROL_PREDICATE_EXECUTING)) { - /* - * A predicate was just completed, get the value of the - * predicate and branch based on that value - */ - walk_state->op = NULL; - status = - acpi_ds_get_predicate_value(walk_state, - ACPI_TO_POINTER - (TRUE)); - if (ACPI_FAILURE(status) - && ((status & AE_CODE_MASK) != - AE_CODE_CONTROL)) { - if (status == AE_AML_NO_RETURN_VALUE) { - ACPI_EXCEPTION((AE_INFO, status, - "Invoked method did not return a value")); - - } - - ACPI_EXCEPTION((AE_INFO, status, - "GetPredicate Failed")); - return_ACPI_STATUS(status); - } - - status = - acpi_ps_next_parse_state(walk_state, op, - status); - } - - acpi_ps_pop_scope(parser_state, &op, - &walk_state->arg_types, - &walk_state->arg_count); - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Popped scope, Op=%p\n", op)); - } else if (walk_state->prev_op) { - - /* We were in the middle of an op */ - - op = walk_state->prev_op; - walk_state->arg_types = walk_state->prev_arg_types; - } - } -#endif - - /* Iterative parsing loop, while there is more AML to process: */ - - while ((parser_state->aml < parser_state->aml_end) || (op)) { - aml_op_start = parser_state->aml; - if (!op) { - status = - acpi_ps_create_op(walk_state, aml_op_start, &op); - if (ACPI_FAILURE(status)) { - if (status == AE_CTRL_PARSE_CONTINUE) { - continue; - } - - if (status == AE_CTRL_PARSE_PENDING) { - status = AE_OK; - } - - status = - acpi_ps_complete_op(walk_state, &op, - status); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - continue; - } - - op->common.aml_offset = walk_state->aml_offset; - - if (walk_state->op_info) { - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", - (u32) op->common.aml_opcode, - walk_state->op_info->name, op, - parser_state->aml, - op->common.aml_offset)); - } - } - - /* - * Start arg_count at zero because we don't know if there are - * any args yet - */ - walk_state->arg_count = 0; - - /* Are there any arguments that must be processed? */ - - if (walk_state->arg_types) { - - /* Get arguments */ - - status = - acpi_ps_get_arguments(walk_state, aml_op_start, op); - if (ACPI_FAILURE(status)) { - status = - acpi_ps_complete_op(walk_state, &op, - status); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - continue; - } - } - - /* Check for arguments that need to be processed */ - - if (walk_state->arg_count) { - /* - * There are arguments (complex ones), push Op and - * prepare for argument - */ - status = acpi_ps_push_scope(parser_state, op, - walk_state->arg_types, - walk_state->arg_count); - if (ACPI_FAILURE(status)) { - status = - acpi_ps_complete_op(walk_state, &op, - status); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - continue; - } - - op = NULL; - continue; - } - - /* - * All arguments have been processed -- Op is complete, - * prepare for next - */ - walk_state->op_info = - acpi_ps_get_opcode_info(op->common.aml_opcode); - if (walk_state->op_info->flags & AML_NAMED) { - if (acpi_gbl_depth) { - acpi_gbl_depth--; - } - - if (op->common.aml_opcode == AML_REGION_OP || - op->common.aml_opcode == AML_DATA_REGION_OP) { - /* - * Skip parsing of control method or opregion body, - * because we don't have enough info in the first pass - * to parse them correctly. - * - * Completed parsing an op_region declaration, we now - * know the length. - */ - op->named.length = - (u32) (parser_state->aml - op->named.data); - } - } - - if (walk_state->op_info->flags & AML_CREATE) { - /* - * Backup to beginning of create_xXXfield declaration (1 for - * Opcode) - * - * body_length is unknown until we parse the body - */ - op->named.length = - (u32) (parser_state->aml - op->named.data); - } - - if (op->common.aml_opcode == AML_BANK_FIELD_OP) { - /* - * Backup to beginning of bank_field declaration - * - * body_length is unknown until we parse the body - */ - op->named.length = - (u32) (parser_state->aml - op->named.data); - } - - /* This op complete, notify the dispatcher */ - - if (walk_state->ascending_callback != NULL) { - walk_state->op = op; - walk_state->opcode = op->common.aml_opcode; - - status = walk_state->ascending_callback(walk_state); - status = - acpi_ps_next_parse_state(walk_state, op, status); - if (status == AE_CTRL_PENDING) { - status = AE_OK; - } - } - - status = acpi_ps_complete_op(walk_state, &op, status); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - } /* while parser_state->Aml */ - - status = acpi_ps_complete_final_op(walk_state, op, status); - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c deleted file mode 100644 index 3693a121b347..000000000000 --- a/drivers/acpi/parser/psopcode.c +++ /dev/null @@ -1,810 +0,0 @@ -/****************************************************************************** - * - * Module Name: psopcode - Parser/Interpreter opcode information table - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_PARSER -ACPI_MODULE_NAME("psopcode") - -static const u8 acpi_gbl_argument_count[] = - { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; - -/******************************************************************************* - * - * NAME: acpi_gbl_aml_op_info - * - * DESCRIPTION: Opcode table. Each entry contains - * The name is a simple ascii string, the operand specifier is an - * ascii string with one letter per operand. The letter specifies - * the operand type. - * - ******************************************************************************/ - -/* - * Summary of opcode types/flags - * - - Opcodes that have associated namespace objects (AML_NSOBJECT flag) - - AML_SCOPE_OP - AML_DEVICE_OP - AML_THERMAL_ZONE_OP - AML_METHOD_OP - AML_POWER_RES_OP - AML_PROCESSOR_OP - AML_FIELD_OP - AML_INDEX_FIELD_OP - AML_BANK_FIELD_OP - AML_NAME_OP - AML_ALIAS_OP - AML_MUTEX_OP - AML_EVENT_OP - AML_REGION_OP - AML_CREATE_FIELD_OP - AML_CREATE_BIT_FIELD_OP - AML_CREATE_BYTE_FIELD_OP - AML_CREATE_WORD_FIELD_OP - AML_CREATE_DWORD_FIELD_OP - AML_CREATE_QWORD_FIELD_OP - AML_INT_NAMEDFIELD_OP - AML_INT_METHODCALL_OP - AML_INT_NAMEPATH_OP - - Opcodes that are "namespace" opcodes (AML_NSOPCODE flag) - - AML_SCOPE_OP - AML_DEVICE_OP - AML_THERMAL_ZONE_OP - AML_METHOD_OP - AML_POWER_RES_OP - AML_PROCESSOR_OP - AML_FIELD_OP - AML_INDEX_FIELD_OP - AML_BANK_FIELD_OP - AML_NAME_OP - AML_ALIAS_OP - AML_MUTEX_OP - AML_EVENT_OP - AML_REGION_OP - AML_INT_NAMEDFIELD_OP - - Opcodes that have an associated namespace node (AML_NSNODE flag) - - AML_SCOPE_OP - AML_DEVICE_OP - AML_THERMAL_ZONE_OP - AML_METHOD_OP - AML_POWER_RES_OP - AML_PROCESSOR_OP - AML_NAME_OP - AML_ALIAS_OP - AML_MUTEX_OP - AML_EVENT_OP - AML_REGION_OP - AML_CREATE_FIELD_OP - AML_CREATE_BIT_FIELD_OP - AML_CREATE_BYTE_FIELD_OP - AML_CREATE_WORD_FIELD_OP - AML_CREATE_DWORD_FIELD_OP - AML_CREATE_QWORD_FIELD_OP - AML_INT_NAMEDFIELD_OP - AML_INT_METHODCALL_OP - AML_INT_NAMEPATH_OP - - Opcodes that define named ACPI objects (AML_NAMED flag) - - AML_SCOPE_OP - AML_DEVICE_OP - AML_THERMAL_ZONE_OP - AML_METHOD_OP - AML_POWER_RES_OP - AML_PROCESSOR_OP - AML_NAME_OP - AML_ALIAS_OP - AML_MUTEX_OP - AML_EVENT_OP - AML_REGION_OP - AML_INT_NAMEDFIELD_OP - - Opcodes that contain executable AML as part of the definition that - must be deferred until needed - - AML_METHOD_OP - AML_VAR_PACKAGE_OP - AML_CREATE_FIELD_OP - AML_CREATE_BIT_FIELD_OP - AML_CREATE_BYTE_FIELD_OP - AML_CREATE_WORD_FIELD_OP - AML_CREATE_DWORD_FIELD_OP - AML_CREATE_QWORD_FIELD_OP - AML_REGION_OP - AML_BUFFER_OP - - Field opcodes - - AML_CREATE_FIELD_OP - AML_FIELD_OP - AML_INDEX_FIELD_OP - AML_BANK_FIELD_OP - - Field "Create" opcodes - - AML_CREATE_FIELD_OP - AML_CREATE_BIT_FIELD_OP - AML_CREATE_BYTE_FIELD_OP - AML_CREATE_WORD_FIELD_OP - AML_CREATE_DWORD_FIELD_OP - AML_CREATE_QWORD_FIELD_OP - - ******************************************************************************/ - -/* - * Master Opcode information table. A summary of everything we know about each - * opcode, all in one place. - */ -const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { -/*! [Begin] no source code translation */ -/* Index Name Parser Args Interpreter Args ObjectType Class Type Flags */ - -/* 00 */ ACPI_OP("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER, - AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), -/* 01 */ ACPI_OP("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER, - AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), -/* 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), -/* 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), -/* 04 */ ACPI_OP("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), -/* 05 */ ACPI_OP("WordConst", ARGP_WORD_OP, ARGI_WORD_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), -/* 06 */ ACPI_OP("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), -/* 07 */ ACPI_OP("String", ARGP_STRING_OP, ARGI_STRING_OP, - ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), -/* 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), -/* 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), -/* 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), -/* 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), -/* 0C */ ACPI_OP("Local0", ARGP_LOCAL0, ARGI_LOCAL0, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), -/* 0D */ ACPI_OP("Local1", ARGP_LOCAL1, ARGI_LOCAL1, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), -/* 0E */ ACPI_OP("Local2", ARGP_LOCAL2, ARGI_LOCAL2, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), -/* 0F */ ACPI_OP("Local3", ARGP_LOCAL3, ARGI_LOCAL3, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), -/* 10 */ ACPI_OP("Local4", ARGP_LOCAL4, ARGI_LOCAL4, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), -/* 11 */ ACPI_OP("Local5", ARGP_LOCAL5, ARGI_LOCAL5, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), -/* 12 */ ACPI_OP("Local6", ARGP_LOCAL6, ARGI_LOCAL6, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), -/* 13 */ ACPI_OP("Local7", ARGP_LOCAL7, ARGI_LOCAL7, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), -/* 14 */ ACPI_OP("Arg0", ARGP_ARG0, ARGI_ARG0, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), -/* 15 */ ACPI_OP("Arg1", ARGP_ARG1, ARGI_ARG1, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), -/* 16 */ ACPI_OP("Arg2", ARGP_ARG2, ARGI_ARG2, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), -/* 17 */ ACPI_OP("Arg3", ARGP_ARG3, ARGI_ARG3, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), -/* 18 */ ACPI_OP("Arg4", ARGP_ARG4, ARGI_ARG4, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), -/* 19 */ ACPI_OP("Arg5", ARGP_ARG5, ARGI_ARG5, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), -/* 1A */ ACPI_OP("Arg6", ARGP_ARG6, ARGI_ARG6, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 3E */ ACPI_OP("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), -/* 3F */ ACPI_OP("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), -/* 40 */ ACPI_OP("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), -/* 41 */ ACPI_OP("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), -/* 42 */ ACPI_OP("Return", ARGP_RETURN_OP, ARGI_RETURN_OP, - ACPI_TYPE_ANY, AML_CLASS_CONTROL, - AML_TYPE_CONTROL, AML_HAS_ARGS), -/* 43 */ ACPI_OP("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), -/* 44 */ ACPI_OP("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP, - ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), -/* 45 */ ACPI_OP("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER, - AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), - -/* Prefixed opcodes (Two-byte opcodes with a prefix op) */ - -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 55 */ ACPI_OP("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_CONSTANT, 0), -/* 56 */ ACPI_OP("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_CONSTANT, 0), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, - ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD | - AML_DEFER), - -/* Internal opcodes that map to invalid AML opcodes */ - -/* 60 */ ACPI_OP("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP, - ACPI_TYPE_ANY, AML_CLASS_INTERNAL, - AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), -/* 61 */ ACPI_OP("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP, - ACPI_TYPE_ANY, AML_CLASS_INTERNAL, - AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), -/* 62 */ ACPI_OP("LGreaterEqual", ARGP_LGREATEREQUAL_OP, - ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, - AML_HAS_ARGS | AML_CONSTANT), -/* 63 */ ACPI_OP("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE), -/* 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), -/* 65 */ ACPI_OP("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP, - ACPI_TYPE_ANY, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, 0), -/* 66 */ ACPI_OP("-ReservedField-", ARGP_RESERVEDFIELD_OP, - ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), -/* 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), -/* 68 */ ACPI_OP("-AccessField-", ARGP_ACCESSFIELD_OP, - ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), -/* 69 */ ACPI_OP("-StaticString", ARGP_STATICSTRING_OP, - ARGI_STATICSTRING_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), -/* 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), -/* 6B */ ACPI_OP("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID, - AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS), -/* 6C */ ACPI_OP("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, - AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS), -/* 6D */ ACPI_OP("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, - AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS), - -/* ACPI 2.0 opcodes */ - -/* 6E */ ACPI_OP("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), - /* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 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), -/* 7A */ ACPI_OP("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP, - ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), -/* 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), -/* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP, - ARGI_DATA_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), -/* 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), - -/* ACPI 3.0 opcodes */ - -/* 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) - -/*! [End] no source code translation !*/ -}; - -/* - * This table is directly indexed by the opcodes, and returns an - * index into the table above - */ -static const u8 acpi_gbl_short_op_index[256] = { -/* 0 1 2 3 4 5 6 7 */ -/* 8 9 A B C D E F */ -/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, -/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, -/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, -/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, -/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D, -/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, -/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, -/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, -/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, -/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, -/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, -/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, -/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, -/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, -/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, -/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, -/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, -}; - -/* - * This table is indexed by the second opcode of the extended opcode - * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info) - */ -static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = { -/* 0 1 2 3 4 5 6 7 */ -/* 8 9 A B C D E F */ -/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, -/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, -/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, -/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK, -/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, -/* 0x88 */ 0x7C, -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_opcode_info - * - * PARAMETERS: Opcode - The AML opcode - * - * RETURN: A pointer to the info about the opcode. - * - * DESCRIPTION: Find AML opcode description based on the opcode. - * NOTE: This procedure must ALWAYS return a valid pointer! - * - ******************************************************************************/ - -const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) -{ - ACPI_FUNCTION_NAME(ps_get_opcode_info); - - /* - * Detect normal 8-bit opcode or extended 16-bit opcode - */ - if (!(opcode & 0xFF00)) { - - /* Simple (8-bit) opcode: 0-255, can't index beyond table */ - - return (&acpi_gbl_aml_op_info - [acpi_gbl_short_op_index[(u8) opcode]]); - } - - if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) && - (((u8) opcode) <= MAX_EXTENDED_OPCODE)) { - - /* Valid extended (16-bit) opcode */ - - return (&acpi_gbl_aml_op_info - [acpi_gbl_long_op_index[(u8) opcode]]); - } - - /* Unknown AML opcode */ - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Unknown AML opcode [%4.4X]\n", opcode)); - - return (&acpi_gbl_aml_op_info[_UNK]); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_opcode_name - * - * PARAMETERS: Opcode - The AML opcode - * - * RETURN: A pointer to the name of the opcode (ASCII String) - * Note: Never returns NULL. - * - * DESCRIPTION: Translate an opcode into a human-readable string - * - ******************************************************************************/ - -char *acpi_ps_get_opcode_name(u16 opcode) -{ -#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) - - const struct acpi_opcode_info *op; - - op = acpi_ps_get_opcode_info(opcode); - - /* Always guaranteed to return a valid pointer */ - - return (op->name); - -#else - return ("OpcodeName unavailable"); - -#endif -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_argument_count - * - * PARAMETERS: op_type - Type associated with the AML opcode - * - * RETURN: Argument count - * - * DESCRIPTION: Obtain the number of expected arguments for an AML opcode - * - ******************************************************************************/ - -u8 acpi_ps_get_argument_count(u32 op_type) -{ - - if (op_type <= AML_TYPE_EXEC_6A_0T_1R) { - return (acpi_gbl_argument_count[op_type]); - } - - return (0); -} diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c deleted file mode 100644 index 9da48fdb811a..000000000000 --- a/drivers/acpi/parser/psparse.c +++ /dev/null @@ -1,701 +0,0 @@ -/****************************************************************************** - * - * Module Name: psparse - Parser top level AML parse routines - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -/* - * Parse the AML and build an operation tree as most interpreters, - * like Perl, do. Parsing is done by hand rather than with a YACC - * generated parser to tightly constrain stack and dynamic memory - * usage. At the same time, parsing is kept flexible and the code - * fairly compact by parsing based on a list of AML opcode - * templates in aml_op_info[] - */ - -#include -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_PARSER -ACPI_MODULE_NAME("psparse") - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_opcode_size - * - * PARAMETERS: Opcode - An AML opcode - * - * RETURN: Size of the opcode, in bytes (1 or 2) - * - * DESCRIPTION: Get the size of the current opcode. - * - ******************************************************************************/ -u32 acpi_ps_get_opcode_size(u32 opcode) -{ - - /* Extended (2-byte) opcode if > 255 */ - - if (opcode > 0x00FF) { - return (2); - } - - /* Otherwise, just a single byte opcode */ - - return (1); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_peek_opcode - * - * PARAMETERS: parser_state - A parser state object - * - * RETURN: Next AML opcode - * - * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) - * - ******************************************************************************/ - -u16 acpi_ps_peek_opcode(struct acpi_parse_state * parser_state) -{ - u8 *aml; - u16 opcode; - - aml = parser_state->aml; - opcode = (u16) ACPI_GET8(aml); - - if (opcode == AML_EXTENDED_OP_PREFIX) { - - /* Extended opcode, get the second opcode byte */ - - aml++; - opcode = (u16) ((opcode << 8) | ACPI_GET8(aml)); - } - - return (opcode); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_complete_this_op - * - * PARAMETERS: walk_state - Current State - * Op - Op to complete - * - * RETURN: Status - * - * DESCRIPTION: Perform any cleanup at the completion of an Op. - * - ******************************************************************************/ - -acpi_status -acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, - union acpi_parse_object * op) -{ - union acpi_parse_object *prev; - union acpi_parse_object *next; - const struct acpi_opcode_info *parent_info; - union acpi_parse_object *replacement_op = NULL; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_PTR(ps_complete_this_op, op); - - /* Check for null Op, can happen if AML code is corrupt */ - - if (!op) { - return_ACPI_STATUS(AE_OK); /* OK for now */ - } - - /* Delete this op and the subtree below it if asked to */ - - if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != - ACPI_PARSE_DELETE_TREE) - || (walk_state->op_info->class == AML_CLASS_ARGUMENT)) { - return_ACPI_STATUS(AE_OK); - } - - /* Make sure that we only delete this subtree */ - - if (op->common.parent) { - prev = op->common.parent->common.value.arg; - if (!prev) { - - /* Nothing more to do */ - - goto cleanup; - } - - /* - * Check if we need to replace the operator and its subtree - * with a return value op (placeholder op) - */ - parent_info = - acpi_ps_get_opcode_info(op->common.parent->common. - aml_opcode); - - switch (parent_info->class) { - case AML_CLASS_CONTROL: - break; - - case AML_CLASS_CREATE: - - /* - * These opcodes contain term_arg operands. The current - * op must be replaced by a placeholder return op - */ - replacement_op = - acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); - if (!replacement_op) { - status = AE_NO_MEMORY; - } - break; - - case AML_CLASS_NAMED_OBJECT: - - /* - * These opcodes contain term_arg operands. The current - * op must be replaced by a placeholder return op - */ - if ((op->common.parent->common.aml_opcode == - AML_REGION_OP) - || (op->common.parent->common.aml_opcode == - AML_DATA_REGION_OP) - || (op->common.parent->common.aml_opcode == - AML_BUFFER_OP) - || (op->common.parent->common.aml_opcode == - AML_PACKAGE_OP) - || (op->common.parent->common.aml_opcode == - AML_BANK_FIELD_OP) - || (op->common.parent->common.aml_opcode == - AML_VAR_PACKAGE_OP)) { - replacement_op = - acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); - if (!replacement_op) { - status = AE_NO_MEMORY; - } - } else - if ((op->common.parent->common.aml_opcode == - AML_NAME_OP) - && (walk_state->pass_number <= - ACPI_IMODE_LOAD_PASS2)) { - if ((op->common.aml_opcode == AML_BUFFER_OP) - || (op->common.aml_opcode == AML_PACKAGE_OP) - || (op->common.aml_opcode == - AML_VAR_PACKAGE_OP)) { - replacement_op = - acpi_ps_alloc_op(op->common. - aml_opcode); - if (!replacement_op) { - status = AE_NO_MEMORY; - } else { - replacement_op->named.data = - op->named.data; - replacement_op->named.length = - op->named.length; - } - } - } - break; - - default: - - replacement_op = - acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); - if (!replacement_op) { - status = AE_NO_MEMORY; - } - } - - /* We must unlink this op from the parent tree */ - - if (prev == op) { - - /* This op is the first in the list */ - - if (replacement_op) { - replacement_op->common.parent = - op->common.parent; - replacement_op->common.value.arg = NULL; - replacement_op->common.node = op->common.node; - op->common.parent->common.value.arg = - replacement_op; - replacement_op->common.next = op->common.next; - } else { - op->common.parent->common.value.arg = - op->common.next; - } - } - - /* Search the parent list */ - - else - while (prev) { - - /* Traverse all siblings in the parent's argument list */ - - next = prev->common.next; - if (next == op) { - if (replacement_op) { - replacement_op->common.parent = - op->common.parent; - replacement_op->common.value. - arg = NULL; - replacement_op->common.node = - op->common.node; - prev->common.next = - replacement_op; - replacement_op->common.next = - op->common.next; - next = NULL; - } else { - prev->common.next = - op->common.next; - next = NULL; - } - } - prev = next; - } - } - - cleanup: - - /* Now we can actually delete the subtree rooted at Op */ - - acpi_ps_delete_parse_tree(op); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_next_parse_state - * - * PARAMETERS: walk_state - Current state - * Op - Current parse op - * callback_status - Status from previous operation - * - * RETURN: Status - * - * DESCRIPTION: Update the parser state based upon the return exception from - * the parser callback. - * - ******************************************************************************/ - -acpi_status -acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, - acpi_status callback_status) -{ - struct acpi_parse_state *parser_state = &walk_state->parser_state; - acpi_status status = AE_CTRL_PENDING; - - ACPI_FUNCTION_TRACE_PTR(ps_next_parse_state, op); - - switch (callback_status) { - case AE_CTRL_TERMINATE: - /* - * A control method was terminated via a RETURN statement. - * The walk of this method is complete. - */ - parser_state->aml = parser_state->aml_end; - status = AE_CTRL_TERMINATE; - break; - - case AE_CTRL_BREAK: - - parser_state->aml = walk_state->aml_last_while; - walk_state->control_state->common.value = FALSE; - status = AE_CTRL_BREAK; - break; - - case AE_CTRL_CONTINUE: - - parser_state->aml = walk_state->aml_last_while; - status = AE_CTRL_CONTINUE; - break; - - case AE_CTRL_PENDING: - - parser_state->aml = walk_state->aml_last_while; - break; - -#if 0 - case AE_CTRL_SKIP: - - parser_state->aml = parser_state->scope->parse_scope.pkg_end; - status = AE_OK; - break; -#endif - - case AE_CTRL_TRUE: - /* - * Predicate of an IF was true, and we are at the matching ELSE. - * Just close out this package - */ - parser_state->aml = acpi_ps_get_next_package_end(parser_state); - status = AE_CTRL_PENDING; - break; - - case AE_CTRL_FALSE: - /* - * Either an IF/WHILE Predicate was false or we encountered a BREAK - * opcode. In both cases, we do not execute the rest of the - * package; We simply close out the parent (finishing the walk of - * this branch of the tree) and continue execution at the parent - * level. - */ - parser_state->aml = parser_state->scope->parse_scope.pkg_end; - - /* In the case of a BREAK, just force a predicate (if any) to FALSE */ - - walk_state->control_state->common.value = FALSE; - status = AE_CTRL_END; - break; - - case AE_CTRL_TRANSFER: - - /* A method call (invocation) -- transfer control */ - - status = AE_CTRL_TRANSFER; - walk_state->prev_op = op; - walk_state->method_call_op = op; - walk_state->method_call_node = - (op->common.value.arg)->common.node; - - /* Will return value (if any) be used by the caller? */ - - walk_state->return_used = - acpi_ds_is_result_used(op, walk_state); - break; - - default: - - status = callback_status; - if ((callback_status & AE_CODE_MASK) == AE_CODE_CONTROL) { - status = AE_OK; - } - break; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_parse_aml - * - * PARAMETERS: walk_state - Current state - * - * - * RETURN: Status - * - * DESCRIPTION: Parse raw AML and return a tree of ops - * - ******************************************************************************/ - -acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) -{ - acpi_status status; - struct acpi_thread_state *thread; - struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list; - struct acpi_walk_state *previous_walk_state; - - ACPI_FUNCTION_TRACE(ps_parse_aml); - - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Entered with WalkState=%p Aml=%p size=%X\n", - walk_state, walk_state->parser_state.aml, - walk_state->parser_state.aml_size)); - - if (!walk_state->parser_state.aml) { - return_ACPI_STATUS(AE_NULL_OBJECT); - } - - /* Create and initialize a new thread state */ - - thread = acpi_ut_create_thread_state(); - if (!thread) { - if (walk_state->method_desc) { - - /* Executing a control method - additional cleanup */ - - acpi_ds_terminate_control_method( - walk_state->method_desc, walk_state); - } - - acpi_ds_delete_walk_state(walk_state); - return_ACPI_STATUS(AE_NO_MEMORY); - } - - walk_state->thread = thread; - - /* - * If executing a method, the starting sync_level is this method's - * sync_level - */ - if (walk_state->method_desc) { - walk_state->thread->current_sync_level = - walk_state->method_desc->method.sync_level; - } - - acpi_ds_push_walk_state(walk_state, thread); - - /* - * This global allows the AML debugger to get a handle to the currently - * executing control method. - */ - acpi_gbl_current_walk_list = thread; - - /* - * Execute the walk loop as long as there is a valid Walk State. This - * handles nested control method invocations without recursion. - */ - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "State=%p\n", walk_state)); - - status = AE_OK; - while (walk_state) { - if (ACPI_SUCCESS(status)) { - /* - * The parse_loop executes AML until the method terminates - * or calls another method. - */ - status = acpi_ps_parse_loop(walk_state); - } - - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Completed one call to walk loop, %s State=%p\n", - acpi_format_exception(status), walk_state)); - - if (status == AE_CTRL_TRANSFER) { - /* - * A method call was detected. - * Transfer control to the called control method - */ - status = - acpi_ds_call_control_method(thread, walk_state, - NULL); - if (ACPI_FAILURE(status)) { - status = - acpi_ds_method_error(status, walk_state); - } - - /* - * If the transfer to the new method method call worked, a new walk - * state was created -- get it - */ - walk_state = acpi_ds_get_current_walk_state(thread); - continue; - } else if (status == AE_CTRL_TERMINATE) { - status = AE_OK; - } else if ((status != AE_OK) && (walk_state->method_desc)) { - - /* Either the method parse or actual execution failed */ - - ACPI_ERROR_METHOD("Method parse/execution failed", - walk_state->method_node, NULL, - status); - - /* Check for possible multi-thread reentrancy problem */ - - if ((status == AE_ALREADY_EXISTS) && - (!walk_state->method_desc->method.mutex)) { - ACPI_INFO((AE_INFO, - "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", - walk_state->method_node->name. - ascii)); - - /* - * Method tried to create an object twice. The probable cause is - * that the method cannot handle reentrancy. - * - * The method is marked not_serialized, but it tried to create - * a named object, causing the second thread entrance to fail. - * Workaround this problem by marking the method permanently - * as Serialized. - */ - walk_state->method_desc->method.method_flags |= - AML_METHOD_SERIALIZED; - walk_state->method_desc->method.sync_level = 0; - } - } - - /* We are done with this walk, move on to the parent if any */ - - walk_state = acpi_ds_pop_walk_state(thread); - - /* Reset the current scope to the beginning of scope stack */ - - acpi_ds_scope_stack_clear(walk_state); - - /* - * If we just returned from the execution of a control method or if we - * encountered an error during the method parse phase, there's lots of - * cleanup to do - */ - if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == - ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) { - acpi_ds_terminate_control_method(walk_state-> - method_desc, - walk_state); - } - - /* Delete this walk state and all linked control states */ - - acpi_ps_cleanup_scope(&walk_state->parser_state); - previous_walk_state = walk_state; - - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "ReturnValue=%p, ImplicitValue=%p State=%p\n", - walk_state->return_desc, - walk_state->implicit_return_obj, walk_state)); - - /* Check if we have restarted a preempted walk */ - - walk_state = acpi_ds_get_current_walk_state(thread); - if (walk_state) { - if (ACPI_SUCCESS(status)) { - /* - * There is another walk state, restart it. - * If the method return value is not used by the parent, - * The object is deleted - */ - if (!previous_walk_state->return_desc) { - /* - * In slack mode execution, if there is no return value - * we should implicitly return zero (0) as a default value. - */ - if (acpi_gbl_enable_interpreter_slack && - !previous_walk_state-> - implicit_return_obj) { - previous_walk_state-> - implicit_return_obj = - acpi_ut_create_internal_object - (ACPI_TYPE_INTEGER); - if (!previous_walk_state-> - implicit_return_obj) { - return_ACPI_STATUS - (AE_NO_MEMORY); - } - - previous_walk_state-> - implicit_return_obj-> - integer.value = 0; - } - - /* Restart the calling control method */ - - status = - acpi_ds_restart_control_method - (walk_state, - previous_walk_state-> - implicit_return_obj); - } else { - /* - * We have a valid return value, delete any implicit - * return value. - */ - acpi_ds_clear_implicit_return - (previous_walk_state); - - status = - acpi_ds_restart_control_method - (walk_state, - previous_walk_state->return_desc); - } - if (ACPI_SUCCESS(status)) { - walk_state->walk_type |= - ACPI_WALK_METHOD_RESTART; - } - } else { - /* On error, delete any return object or implicit return */ - - acpi_ut_remove_reference(previous_walk_state-> - return_desc); - acpi_ds_clear_implicit_return - (previous_walk_state); - } - } - - /* - * Just completed a 1st-level method, save the final internal return - * value (if any) - */ - else if (previous_walk_state->caller_return_desc) { - if (previous_walk_state->implicit_return_obj) { - *(previous_walk_state->caller_return_desc) = - previous_walk_state->implicit_return_obj; - } else { - /* NULL if no return value */ - - *(previous_walk_state->caller_return_desc) = - previous_walk_state->return_desc; - } - } else { - if (previous_walk_state->return_desc) { - - /* Caller doesn't want it, must delete it */ - - acpi_ut_remove_reference(previous_walk_state-> - return_desc); - } - if (previous_walk_state->implicit_return_obj) { - - /* Caller doesn't want it, must delete it */ - - acpi_ut_remove_reference(previous_walk_state-> - implicit_return_obj); - } - } - - acpi_ds_delete_walk_state(previous_walk_state); - } - - /* Normal exit */ - - acpi_ex_release_all_mutexes(thread); - acpi_ut_delete_generic_state(ACPI_CAST_PTR - (union acpi_generic_state, thread)); - acpi_gbl_current_walk_list = prev_walk_list; - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c deleted file mode 100644 index 22929ca1ffe4..000000000000 --- a/drivers/acpi/parser/psscope.c +++ /dev/null @@ -1,265 +0,0 @@ -/****************************************************************************** - * - * Module Name: psscope - Parser scope stack management routines - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_PARSER -ACPI_MODULE_NAME("psscope") - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_parent_scope - * - * PARAMETERS: parser_state - Current parser state object - * - * RETURN: Pointer to an Op object - * - * DESCRIPTION: Get parent of current op being parsed - * - ******************************************************************************/ -union acpi_parse_object *acpi_ps_get_parent_scope(struct acpi_parse_state - *parser_state) -{ - - return (parser_state->scope->parse_scope.op); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_has_completed_scope - * - * PARAMETERS: parser_state - Current parser state object - * - * RETURN: Boolean, TRUE = scope completed. - * - * DESCRIPTION: Is parsing of current argument complete? Determined by - * 1) AML pointer is at or beyond the end of the scope - * 2) The scope argument count has reached zero. - * - ******************************************************************************/ - -u8 acpi_ps_has_completed_scope(struct acpi_parse_state * parser_state) -{ - - return ((u8) - ((parser_state->aml >= parser_state->scope->parse_scope.arg_end - || !parser_state->scope->parse_scope.arg_count))); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_init_scope - * - * PARAMETERS: parser_state - Current parser state object - * Root - the Root Node of this new scope - * - * RETURN: Status - * - * DESCRIPTION: Allocate and init a new scope object - * - ******************************************************************************/ - -acpi_status -acpi_ps_init_scope(struct acpi_parse_state * parser_state, - union acpi_parse_object * root_op) -{ - union acpi_generic_state *scope; - - ACPI_FUNCTION_TRACE_PTR(ps_init_scope, root_op); - - scope = acpi_ut_create_generic_state(); - if (!scope) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_RPSCOPE; - scope->parse_scope.op = root_op; - scope->parse_scope.arg_count = ACPI_VAR_ARGS; - scope->parse_scope.arg_end = parser_state->aml_end; - scope->parse_scope.pkg_end = parser_state->aml_end; - - parser_state->scope = scope; - parser_state->start_op = root_op; - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_push_scope - * - * PARAMETERS: parser_state - Current parser state object - * Op - Current op to be pushed - * remaining_args - List of args remaining - * arg_count - Fixed or variable number of args - * - * RETURN: Status - * - * DESCRIPTION: Push current op to begin parsing its argument - * - ******************************************************************************/ - -acpi_status -acpi_ps_push_scope(struct acpi_parse_state *parser_state, - union acpi_parse_object *op, - u32 remaining_args, u32 arg_count) -{ - union acpi_generic_state *scope; - - ACPI_FUNCTION_TRACE_PTR(ps_push_scope, op); - - scope = acpi_ut_create_generic_state(); - if (!scope) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_PSCOPE; - scope->parse_scope.op = op; - scope->parse_scope.arg_list = remaining_args; - scope->parse_scope.arg_count = arg_count; - scope->parse_scope.pkg_end = parser_state->pkg_end; - - /* Push onto scope stack */ - - acpi_ut_push_generic_state(&parser_state->scope, scope); - - if (arg_count == ACPI_VAR_ARGS) { - - /* Multiple arguments */ - - scope->parse_scope.arg_end = parser_state->pkg_end; - } else { - /* Single argument */ - - scope->parse_scope.arg_end = ACPI_TO_POINTER(ACPI_MAX_PTR); - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_pop_scope - * - * PARAMETERS: parser_state - Current parser state object - * Op - Where the popped op is returned - * arg_list - Where the popped "next argument" is - * returned - * arg_count - Count of objects in arg_list - * - * RETURN: Status - * - * DESCRIPTION: Return to parsing a previous op - * - ******************************************************************************/ - -void -acpi_ps_pop_scope(struct acpi_parse_state *parser_state, - union acpi_parse_object **op, u32 * arg_list, u32 * arg_count) -{ - union acpi_generic_state *scope = parser_state->scope; - - ACPI_FUNCTION_TRACE(ps_pop_scope); - - /* Only pop the scope if there is in fact a next scope */ - - if (scope->common.next) { - scope = acpi_ut_pop_generic_state(&parser_state->scope); - - /* Return to parsing previous op */ - - *op = scope->parse_scope.op; - *arg_list = scope->parse_scope.arg_list; - *arg_count = scope->parse_scope.arg_count; - parser_state->pkg_end = scope->parse_scope.pkg_end; - - /* All done with this scope state structure */ - - acpi_ut_delete_generic_state(scope); - } else { - /* Empty parse stack, prepare to fetch next opcode */ - - *op = NULL; - *arg_list = 0; - *arg_count = 0; - } - - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Popped Op %p Args %X\n", *op, *arg_count)); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_cleanup_scope - * - * PARAMETERS: parser_state - Current parser state object - * - * RETURN: None - * - * DESCRIPTION: Destroy available list, remaining stack levels, and return - * root scope - * - ******************************************************************************/ - -void acpi_ps_cleanup_scope(struct acpi_parse_state *parser_state) -{ - union acpi_generic_state *scope; - - ACPI_FUNCTION_TRACE_PTR(ps_cleanup_scope, parser_state); - - if (!parser_state) { - return_VOID; - } - - /* Delete anything on the scope stack */ - - while (parser_state->scope) { - scope = acpi_ut_pop_generic_state(&parser_state->scope); - acpi_ut_delete_generic_state(scope); - } - - return_VOID; -} diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c deleted file mode 100644 index 8e73fbf00971..000000000000 --- a/drivers/acpi/parser/pstree.c +++ /dev/null @@ -1,312 +0,0 @@ -/****************************************************************************** - * - * Module Name: pstree - Parser op tree manipulation/traversal/search - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_PARSER -ACPI_MODULE_NAME("pstree") - -/* Local prototypes */ -#ifdef ACPI_OBSOLETE_FUNCTIONS -union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op); -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_arg - * - * PARAMETERS: Op - Get an argument for this op - * Argn - Nth argument to get - * - * RETURN: The argument (as an Op object). NULL if argument does not exist - * - * DESCRIPTION: Get the specified op's argument. - * - ******************************************************************************/ - -union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn) -{ - union acpi_parse_object *arg = NULL; - const struct acpi_opcode_info *op_info; - - ACPI_FUNCTION_ENTRY(); - - /* Get the info structure for this opcode */ - - op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); - if (op_info->class == AML_CLASS_UNKNOWN) { - - /* Invalid opcode or ASCII character */ - - return (NULL); - } - - /* Check if this opcode requires argument sub-objects */ - - if (!(op_info->flags & AML_HAS_ARGS)) { - - /* Has no linked argument objects */ - - return (NULL); - } - - /* Get the requested argument object */ - - arg = op->common.value.arg; - while (arg && argn) { - argn--; - arg = arg->common.next; - } - - return (arg); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_append_arg - * - * PARAMETERS: Op - Append an argument to this Op. - * Arg - Argument Op to append - * - * RETURN: None. - * - * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK) - * - ******************************************************************************/ - -void -acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) -{ - union acpi_parse_object *prev_arg; - const struct acpi_opcode_info *op_info; - - ACPI_FUNCTION_ENTRY(); - - if (!op) { - return; - } - - /* Get the info structure for this opcode */ - - op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); - if (op_info->class == AML_CLASS_UNKNOWN) { - - /* Invalid opcode */ - - ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X", - op->common.aml_opcode)); - return; - } - - /* Check if this opcode requires argument sub-objects */ - - if (!(op_info->flags & AML_HAS_ARGS)) { - - /* Has no linked argument objects */ - - return; - } - - /* Append the argument to the linked argument list */ - - if (op->common.value.arg) { - - /* Append to existing argument list */ - - prev_arg = op->common.value.arg; - while (prev_arg->common.next) { - prev_arg = prev_arg->common.next; - } - prev_arg->common.next = arg; - } else { - /* No argument list, this will be the first argument */ - - op->common.value.arg = arg; - } - - /* Set the parent in this arg and any args linked after it */ - - while (arg) { - arg->common.parent = op; - arg = arg->common.next; - - op->common.arg_list_length++; - } -} - -#ifdef ACPI_FUTURE_USAGE -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_depth_next - * - * PARAMETERS: Origin - Root of subtree to search - * Op - Last (previous) Op that was found - * - * RETURN: Next Op found in the search. - * - * DESCRIPTION: Get next op in tree (walking the tree in depth-first order) - * Return NULL when reaching "origin" or when walking up from root - * - ******************************************************************************/ - -union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin, - union acpi_parse_object *op) -{ - union acpi_parse_object *next = NULL; - union acpi_parse_object *parent; - union acpi_parse_object *arg; - - ACPI_FUNCTION_ENTRY(); - - if (!op) { - return (NULL); - } - - /* Look for an argument or child */ - - next = acpi_ps_get_arg(op, 0); - if (next) { - return (next); - } - - /* Look for a sibling */ - - next = op->common.next; - if (next) { - return (next); - } - - /* Look for a sibling of parent */ - - parent = op->common.parent; - - while (parent) { - arg = acpi_ps_get_arg(parent, 0); - while (arg && (arg != origin) && (arg != op)) { - arg = arg->common.next; - } - - if (arg == origin) { - - /* Reached parent of origin, end search */ - - return (NULL); - } - - if (parent->common.next) { - - /* Found sibling of parent */ - - return (parent->common.next); - } - - op = parent; - parent = parent->common.parent; - } - - return (next); -} - -#ifdef ACPI_OBSOLETE_FUNCTIONS -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_child - * - * PARAMETERS: Op - Get the child of this Op - * - * RETURN: Child Op, Null if none is found. - * - * DESCRIPTION: Get op's children or NULL if none - * - ******************************************************************************/ - -union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op) -{ - union acpi_parse_object *child = NULL; - - ACPI_FUNCTION_ENTRY(); - - switch (op->common.aml_opcode) { - case AML_SCOPE_OP: - case AML_ELSE_OP: - case AML_DEVICE_OP: - case AML_THERMAL_ZONE_OP: - case AML_INT_METHODCALL_OP: - - child = acpi_ps_get_arg(op, 0); - break; - - case AML_BUFFER_OP: - case AML_PACKAGE_OP: - case AML_METHOD_OP: - case AML_IF_OP: - case AML_WHILE_OP: - case AML_FIELD_OP: - - child = acpi_ps_get_arg(op, 1); - break; - - case AML_POWER_RES_OP: - case AML_INDEX_FIELD_OP: - - child = acpi_ps_get_arg(op, 2); - break; - - case AML_PROCESSOR_OP: - case AML_BANK_FIELD_OP: - - child = acpi_ps_get_arg(op, 3); - break; - - default: - /* All others have no children */ - break; - } - - return (child); -} -#endif -#endif /* ACPI_FUTURE_USAGE */ diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c deleted file mode 100644 index eec7d624db8e..000000000000 --- a/drivers/acpi/parser/psutils.c +++ /dev/null @@ -1,244 +0,0 @@ -/****************************************************************************** - * - * Module Name: psutils - Parser miscellaneous utilities (Parser only) - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_PARSER -ACPI_MODULE_NAME("psutils") - -/******************************************************************************* - * - * FUNCTION: acpi_ps_create_scope_op - * - * PARAMETERS: None - * - * RETURN: A new Scope object, null on failure - * - * DESCRIPTION: Create a Scope and associated namepath op with the root name - * - ******************************************************************************/ -union acpi_parse_object *acpi_ps_create_scope_op(void) -{ - union acpi_parse_object *scope_op; - - scope_op = acpi_ps_alloc_op(AML_SCOPE_OP); - if (!scope_op) { - return (NULL); - } - - scope_op->named.name = ACPI_ROOT_NAME; - return (scope_op); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_init_op - * - * PARAMETERS: Op - A newly allocated Op object - * Opcode - Opcode to store in the Op - * - * RETURN: None - * - * DESCRIPTION: Initialize a parse (Op) object - * - ******************************************************************************/ - -void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode) -{ - ACPI_FUNCTION_ENTRY(); - - op->common.descriptor_type = ACPI_DESC_TYPE_PARSER; - op->common.aml_opcode = opcode; - - ACPI_DISASM_ONLY_MEMBERS(ACPI_STRNCPY(op->common.aml_op_name, - (acpi_ps_get_opcode_info - (opcode))->name, - sizeof(op->common.aml_op_name))); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_alloc_op - * - * PARAMETERS: Opcode - Opcode that will be stored in the new Op - * - * RETURN: Pointer to the new Op, null on failure - * - * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on - * opcode. A cache of opcodes is available for the pure - * GENERIC_OP, since this is by far the most commonly used. - * - ******************************************************************************/ - -union acpi_parse_object *acpi_ps_alloc_op(u16 opcode) -{ - union acpi_parse_object *op; - const struct acpi_opcode_info *op_info; - u8 flags = ACPI_PARSEOP_GENERIC; - - ACPI_FUNCTION_ENTRY(); - - op_info = acpi_ps_get_opcode_info(opcode); - - /* Determine type of parse_op required */ - - if (op_info->flags & AML_DEFER) { - flags = ACPI_PARSEOP_DEFERRED; - } else if (op_info->flags & AML_NAMED) { - flags = ACPI_PARSEOP_NAMED; - } else if (opcode == AML_INT_BYTELIST_OP) { - flags = ACPI_PARSEOP_BYTELIST; - } - - /* Allocate the minimum required size object */ - - if (flags == ACPI_PARSEOP_GENERIC) { - - /* The generic op (default) is by far the most common (16 to 1) */ - - op = acpi_os_acquire_object(acpi_gbl_ps_node_cache); - } else { - /* Extended parseop */ - - op = acpi_os_acquire_object(acpi_gbl_ps_node_ext_cache); - } - - /* Initialize the Op */ - - if (op) { - acpi_ps_init_op(op, opcode); - op->common.flags = flags; - } - - return (op); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_free_op - * - * PARAMETERS: Op - Op to be freed - * - * RETURN: None. - * - * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list - * or actually free it. - * - ******************************************************************************/ - -void acpi_ps_free_op(union acpi_parse_object *op) -{ - ACPI_FUNCTION_NAME(ps_free_op); - - if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n", - op)); - } - - if (op->common.flags & ACPI_PARSEOP_GENERIC) { - (void)acpi_os_release_object(acpi_gbl_ps_node_cache, op); - } else { - (void)acpi_os_release_object(acpi_gbl_ps_node_ext_cache, op); - } -} - -/******************************************************************************* - * - * FUNCTION: Utility functions - * - * DESCRIPTION: Low level character and object functions - * - ******************************************************************************/ - -/* - * Is "c" a namestring lead character? - */ -u8 acpi_ps_is_leading_char(u32 c) -{ - return ((u8) (c == '_' || (c >= 'A' && c <= 'Z'))); -} - -/* - * Is "c" a namestring prefix character? - */ -u8 acpi_ps_is_prefix_char(u32 c) -{ - return ((u8) (c == '\\' || c == '^')); -} - -/* - * Get op's name (4-byte name segment) or 0 if unnamed - */ -#ifdef ACPI_FUTURE_USAGE -u32 acpi_ps_get_name(union acpi_parse_object * op) -{ - - /* The "generic" object has no name associated with it */ - - if (op->common.flags & ACPI_PARSEOP_GENERIC) { - return (0); - } - - /* Only the "Extended" parse objects have a name */ - - return (op->named.name); -} -#endif /* ACPI_FUTURE_USAGE */ - -/* - * Set op's name - */ -void acpi_ps_set_name(union acpi_parse_object *op, u32 name) -{ - - /* The "generic" object has no name associated with it */ - - if (op->common.flags & ACPI_PARSEOP_GENERIC) { - return; - } - - op->named.name = name; -} diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c deleted file mode 100644 index dacc4228ba1a..000000000000 --- a/drivers/acpi/parser/pswalk.c +++ /dev/null @@ -1,110 +0,0 @@ -/****************************************************************************** - * - * Module Name: pswalk - Parser routines to walk parsed op tree(s) - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_PARSER -ACPI_MODULE_NAME("pswalk") - -/******************************************************************************* - * - * FUNCTION: acpi_ps_delete_parse_tree - * - * PARAMETERS: subtree_root - Root of tree (or subtree) to delete - * - * RETURN: None - * - * DESCRIPTION: Delete a portion of or an entire parse tree. - * - ******************************************************************************/ -void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root) -{ - union acpi_parse_object *op = subtree_root; - union acpi_parse_object *next = NULL; - union acpi_parse_object *parent = NULL; - - ACPI_FUNCTION_TRACE_PTR(ps_delete_parse_tree, subtree_root); - - /* Visit all nodes in the subtree */ - - while (op) { - - /* Check if we are not ascending */ - - if (op != parent) { - - /* Look for an argument or child of the current op */ - - next = acpi_ps_get_arg(op, 0); - if (next) { - - /* Still going downward in tree (Op is not completed yet) */ - - op = next; - continue; - } - } - - /* No more children, this Op is complete. */ - - next = op->common.next; - parent = op->common.parent; - - acpi_ps_free_op(op); - - /* If we are back to the starting point, the walk is complete. */ - - if (op == subtree_root) { - return_VOID; - } - if (next) { - op = next; - } else { - op = parent; - } - } - - return_VOID; -} diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c deleted file mode 100644 index 98c31a893706..000000000000 --- a/drivers/acpi/parser/psxface.c +++ /dev/null @@ -1,385 +0,0 @@ -/****************************************************************************** - * - * Module Name: psxface - Parser external interfaces - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_PARSER -ACPI_MODULE_NAME("psxface") - -/* Local Prototypes */ -static void acpi_ps_start_trace(struct acpi_evaluate_info *info); - -static void acpi_ps_stop_trace(struct acpi_evaluate_info *info); - -static void -acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action); - -/******************************************************************************* - * - * FUNCTION: acpi_debug_trace - * - * PARAMETERS: method_name - Valid ACPI name string - * debug_level - Optional level mask. 0 to use default - * debug_layer - Optional layer mask. 0 to use default - * Flags - bit 1: one shot(1) or persistent(0) - * - * RETURN: Status - * - * DESCRIPTION: External interface to enable debug tracing during control - * method execution - * - ******************************************************************************/ - -acpi_status -acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags) -{ - acpi_status status; - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* TBDs: Validate name, allow full path or just nameseg */ - - acpi_gbl_trace_method_name = *ACPI_CAST_PTR(u32, name); - acpi_gbl_trace_flags = flags; - - if (debug_level) { - acpi_gbl_trace_dbg_level = debug_level; - } - if (debug_layer) { - acpi_gbl_trace_dbg_layer = debug_layer; - } - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_start_trace - * - * PARAMETERS: Info - Method info struct - * - * RETURN: None - * - * DESCRIPTION: Start control method execution trace - * - ******************************************************************************/ - -static void acpi_ps_start_trace(struct acpi_evaluate_info *info) -{ - acpi_status status; - - ACPI_FUNCTION_ENTRY(); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return; - } - - if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { - goto exit; - } - - acpi_gbl_original_dbg_level = acpi_dbg_level; - acpi_gbl_original_dbg_layer = acpi_dbg_layer; - - acpi_dbg_level = 0x00FFFFFF; - acpi_dbg_layer = ACPI_UINT32_MAX; - - if (acpi_gbl_trace_dbg_level) { - acpi_dbg_level = acpi_gbl_trace_dbg_level; - } - if (acpi_gbl_trace_dbg_layer) { - acpi_dbg_layer = acpi_gbl_trace_dbg_layer; - } - - exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_stop_trace - * - * PARAMETERS: Info - Method info struct - * - * RETURN: None - * - * DESCRIPTION: Stop control method execution trace - * - ******************************************************************************/ - -static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) -{ - acpi_status status; - - ACPI_FUNCTION_ENTRY(); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return; - } - - if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { - goto exit; - } - - /* Disable further tracing if type is one-shot */ - - if (acpi_gbl_trace_flags & 1) { - acpi_gbl_trace_method_name = 0; - acpi_gbl_trace_dbg_level = 0; - acpi_gbl_trace_dbg_layer = 0; - } - - acpi_dbg_level = acpi_gbl_original_dbg_level; - acpi_dbg_layer = acpi_gbl_original_dbg_layer; - - exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_execute_method - * - * PARAMETERS: Info - Method info block, contains: - * Node - Method Node to execute - * obj_desc - Method object - * Parameters - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * parameter_type - Type of Parameter list - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * pass_number - Parse or execute pass - * - * RETURN: Status - * - * DESCRIPTION: Execute a control method - * - ******************************************************************************/ - -acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) -{ - acpi_status status; - union acpi_parse_object *op; - struct acpi_walk_state *walk_state; - - ACPI_FUNCTION_TRACE(ps_execute_method); - - /* Validate the Info and method Node */ - - if (!info || !info->resolved_node) { - return_ACPI_STATUS(AE_NULL_ENTRY); - } - - /* Init for new method, wait on concurrency semaphore */ - - status = - acpi_ds_begin_method_execution(info->resolved_node, info->obj_desc, - NULL); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * The caller "owns" the parameters, so give each one an extra reference - */ - acpi_ps_update_parameter_list(info, REF_INCREMENT); - - /* Begin tracing if requested */ - - acpi_ps_start_trace(info); - - /* - * Execute the method. Performs parse simultaneously - */ - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n", - info->resolved_node->name.ascii, info->resolved_node, - info->obj_desc)); - - /* Create and init a Root Node */ - - op = acpi_ps_create_scope_op(); - if (!op) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Create and initialize a new walk state */ - - info->pass_number = ACPI_IMODE_EXECUTE; - walk_state = - acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL, - NULL, NULL); - if (!walk_state) { - status = AE_NO_MEMORY; - goto cleanup; - } - - status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node, - info->obj_desc->method.aml_start, - info->obj_desc->method.aml_length, info, - info->pass_number); - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - goto cleanup; - } - - /* Invoke an internal method if necessary */ - - if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { - status = info->obj_desc->method.implementation(walk_state); - info->return_object = walk_state->return_desc; - - /* Cleanup states */ - - acpi_ds_scope_stack_clear(walk_state); - acpi_ps_cleanup_scope(&walk_state->parser_state); - acpi_ds_terminate_control_method(walk_state->method_desc, - walk_state); - acpi_ds_delete_walk_state(walk_state); - goto cleanup; - } - - /* - * Start method evaluation with an implicit return of zero. - * This is done for Windows compatibility. - */ - if (acpi_gbl_enable_interpreter_slack) { - walk_state->implicit_return_obj = - acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!walk_state->implicit_return_obj) { - status = AE_NO_MEMORY; - acpi_ds_delete_walk_state(walk_state); - goto cleanup; - } - - walk_state->implicit_return_obj->integer.value = 0; - } - - /* Parse the AML */ - - status = acpi_ps_parse_aml(walk_state); - - /* walk_state was deleted by parse_aml */ - - cleanup: - acpi_ps_delete_parse_tree(op); - - /* End optional tracing */ - - acpi_ps_stop_trace(info); - - /* Take away the extra reference that we gave the parameters above */ - - acpi_ps_update_parameter_list(info, REF_DECREMENT); - - /* Exit now if error above */ - - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * If the method has returned an object, signal this to the caller with - * a control exception code - */ - if (info->return_object) { - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n", - info->return_object)); - ACPI_DUMP_STACK_ENTRY(info->return_object); - - status = AE_CTRL_RETURN_VALUE; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_update_parameter_list - * - * PARAMETERS: Info - See struct acpi_evaluate_info - * (Used: parameter_type and Parameters) - * Action - Add or Remove reference - * - * RETURN: Status - * - * DESCRIPTION: Update reference count on all method parameter objects - * - ******************************************************************************/ - -static void -acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action) -{ - u32 i; - - if (info->parameters) { - - /* Update reference count for each parameter */ - - for (i = 0; info->parameters[i]; i++) { - - /* Ignore errors, just do them all */ - - (void)acpi_ut_update_object_reference(info-> - parameters[i], - action); - } - } -} diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c new file mode 100644 index 000000000000..1c4851ff2657 --- /dev/null +++ b/drivers/acpi/proc.c @@ -0,0 +1,520 @@ +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_X86 +#include +#endif + +#include "sleep.h" + +#define _COMPONENT ACPI_SYSTEM_COMPONENT + +/* + * this file provides support for: + * /proc/acpi/sleep + * /proc/acpi/alarm + * /proc/acpi/wakeup + */ + +ACPI_MODULE_NAME("sleep") +#ifdef CONFIG_ACPI_PROCFS +static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset) +{ + int i; + + for (i = 0; i <= ACPI_STATE_S5; i++) { + if (sleep_states[i]) { + seq_printf(seq, "S%d ", i); + } + } + + seq_puts(seq, "\n"); + + return 0; +} + +static int acpi_system_sleep_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_system_sleep_seq_show, PDE(inode)->data); +} + +static ssize_t +acpi_system_write_sleep(struct file *file, + const char __user * buffer, size_t count, loff_t * ppos) +{ + char str[12]; + u32 state = 0; + int error = 0; + + if (count > sizeof(str) - 1) + goto Done; + memset(str, 0, sizeof(str)); + if (copy_from_user(str, buffer, count)) + return -EFAULT; + + /* Check for S4 bios request */ + if (!strcmp(str, "4b")) { + error = acpi_suspend(4); + goto Done; + } + state = simple_strtoul(str, NULL, 0); +#ifdef CONFIG_HIBERNATION + if (state == 4) { + error = hibernate(); + goto Done; + } +#endif + error = acpi_suspend(state); + Done: + return error ? error : count; +} +#endif /* CONFIG_ACPI_PROCFS */ + +#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || !defined(CONFIG_X86) +/* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */ +#else +#define HAVE_ACPI_LEGACY_ALARM +#endif + +#ifdef HAVE_ACPI_LEGACY_ALARM + +static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) +{ + u32 sec, min, hr; + u32 day, mo, yr, cent = 0; + unsigned char rtc_control = 0; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + + sec = CMOS_READ(RTC_SECONDS_ALARM); + min = CMOS_READ(RTC_MINUTES_ALARM); + hr = CMOS_READ(RTC_HOURS_ALARM); + rtc_control = CMOS_READ(RTC_CONTROL); + + /* If we ever get an FACP with proper values... */ + if (acpi_gbl_FADT.day_alarm) + /* ACPI spec: only low 6 its should be cared */ + day = CMOS_READ(acpi_gbl_FADT.day_alarm) & 0x3F; + else + day = CMOS_READ(RTC_DAY_OF_MONTH); + if (acpi_gbl_FADT.month_alarm) + mo = CMOS_READ(acpi_gbl_FADT.month_alarm); + else + mo = CMOS_READ(RTC_MONTH); + if (acpi_gbl_FADT.century) + cent = CMOS_READ(acpi_gbl_FADT.century); + + yr = CMOS_READ(RTC_YEAR); + + spin_unlock_irqrestore(&rtc_lock, flags); + + if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + sec = bcd2bin(sec); + min = bcd2bin(min); + hr = bcd2bin(hr); + day = bcd2bin(day); + mo = bcd2bin(mo); + yr = bcd2bin(yr); + cent = bcd2bin(cent); + } + + /* we're trusting the FADT (see above) */ + if (!acpi_gbl_FADT.century) + /* If we're not trusting the FADT, we should at least make it + * right for _this_ century... ehm, what is _this_ century? + * + * TBD: + * ASAP: find piece of code in the kernel, e.g. star tracker driver, + * which we can trust to determine the century correctly. Atom + * watch driver would be nice, too... + * + * if that has not happened, change for first release in 2050: + * if (yr<50) + * yr += 2100; + * else + * yr += 2000; // current line of code + * + * if that has not happened either, please do on 2099/12/31:23:59:59 + * s/2000/2100 + * + */ + yr += 2000; + else + yr += cent * 100; + + seq_printf(seq, "%4.4u-", yr); + (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo); + (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day); + (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr); + (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min); + (sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec); + + return 0; +} + +static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_system_alarm_seq_show, PDE(inode)->data); +} + +static int get_date_field(char **p, u32 * value) +{ + char *next = NULL; + char *string_end = NULL; + int result = -EINVAL; + + /* + * Try to find delimeter, only to insert null. The end of the + * string won't have one, but is still valid. + */ + if (*p == NULL) + return result; + + next = strpbrk(*p, "- :"); + if (next) + *next++ = '\0'; + + *value = simple_strtoul(*p, &string_end, 10); + + /* Signal success if we got a good digit */ + if (string_end != *p) + result = 0; + + if (next) + *p = next; + else + *p = NULL; + + return result; +} + +/* Read a possibly BCD register, always return binary */ +static u32 cmos_bcd_read(int offset, int rtc_control) +{ + u32 val = CMOS_READ(offset); + if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + val = bcd2bin(val); + return val; +} + +/* Write binary value into possibly BCD register */ +static void cmos_bcd_write(u32 val, int offset, int rtc_control) +{ + if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + val = bin2bcd(val); + CMOS_WRITE(val, offset); +} + +static ssize_t +acpi_system_write_alarm(struct file *file, + const char __user * buffer, size_t count, loff_t * ppos) +{ + int result = 0; + char alarm_string[30] = { '\0' }; + char *p = alarm_string; + u32 sec, min, hr, day, mo, yr; + int adjust = 0; + unsigned char rtc_control = 0; + + if (count > sizeof(alarm_string) - 1) + return -EINVAL; + + if (copy_from_user(alarm_string, buffer, count)) + return -EFAULT; + + alarm_string[count] = '\0'; + + /* check for time adjustment */ + if (alarm_string[0] == '+') { + p++; + adjust = 1; + } + + if ((result = get_date_field(&p, &yr))) + goto end; + if ((result = get_date_field(&p, &mo))) + goto end; + if ((result = get_date_field(&p, &day))) + goto end; + if ((result = get_date_field(&p, &hr))) + goto end; + if ((result = get_date_field(&p, &min))) + goto end; + if ((result = get_date_field(&p, &sec))) + goto end; + + spin_lock_irq(&rtc_lock); + + rtc_control = CMOS_READ(RTC_CONTROL); + + if (adjust) { + yr += cmos_bcd_read(RTC_YEAR, rtc_control); + mo += cmos_bcd_read(RTC_MONTH, rtc_control); + day += cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); + hr += cmos_bcd_read(RTC_HOURS, rtc_control); + min += cmos_bcd_read(RTC_MINUTES, rtc_control); + sec += cmos_bcd_read(RTC_SECONDS, rtc_control); + } + + spin_unlock_irq(&rtc_lock); + + if (sec > 59) { + min += sec/60; + sec = sec%60; + } + if (min > 59) { + hr += min/60; + min = min%60; + } + if (hr > 23) { + day += hr/24; + hr = hr%24; + } + if (day > 31) { + mo += day/32; + day = day%32; + } + if (mo > 12) { + yr += mo/13; + mo = mo%13; + } + + spin_lock_irq(&rtc_lock); + /* + * Disable alarm interrupt before setting alarm timer or else + * when ACPI_EVENT_RTC is enabled, a spurious ACPI interrupt occurs + */ + rtc_control &= ~RTC_AIE; + CMOS_WRITE(rtc_control, RTC_CONTROL); + CMOS_READ(RTC_INTR_FLAGS); + + /* write the fields the rtc knows about */ + cmos_bcd_write(hr, RTC_HOURS_ALARM, rtc_control); + cmos_bcd_write(min, RTC_MINUTES_ALARM, rtc_control); + cmos_bcd_write(sec, RTC_SECONDS_ALARM, rtc_control); + + /* + * If the system supports an enhanced alarm it will have non-zero + * offsets into the CMOS RAM here -- which for some reason are pointing + * to the RTC area of memory. + */ + if (acpi_gbl_FADT.day_alarm) + cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control); + if (acpi_gbl_FADT.month_alarm) + cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control); + if (acpi_gbl_FADT.century) { + if (adjust) + yr += cmos_bcd_read(acpi_gbl_FADT.century, rtc_control) * 100; + cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control); + } + /* enable the rtc alarm interrupt */ + rtc_control |= RTC_AIE; + CMOS_WRITE(rtc_control, RTC_CONTROL); + CMOS_READ(RTC_INTR_FLAGS); + + spin_unlock_irq(&rtc_lock); + + acpi_clear_event(ACPI_EVENT_RTC); + acpi_enable_event(ACPI_EVENT_RTC, 0); + + *ppos += count; + + result = 0; + end: + return result ? result : count; +} +#endif /* HAVE_ACPI_LEGACY_ALARM */ + +extern struct list_head acpi_wakeup_device_list; +extern spinlock_t acpi_device_lock; + +static int +acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) +{ + struct list_head *node, *next; + + seq_printf(seq, "Device\tS-state\t Status Sysfs node\n"); + + spin_lock(&acpi_device_lock); + list_for_each_safe(node, next, &acpi_wakeup_device_list) { + struct acpi_device *dev = + container_of(node, struct acpi_device, wakeup_list); + struct device *ldev; + + if (!dev->wakeup.flags.valid) + continue; + spin_unlock(&acpi_device_lock); + + ldev = acpi_get_physical_device(dev->handle); + seq_printf(seq, "%s\t S%d\t%c%-8s ", + dev->pnp.bus_id, + (u32) dev->wakeup.sleep_state, + dev->wakeup.flags.run_wake ? '*' : ' ', + dev->wakeup.state.enabled ? "enabled" : "disabled"); + if (ldev) + seq_printf(seq, "%s:%s", + ldev->bus ? ldev->bus->name : "no-bus", + dev_name(ldev)); + seq_printf(seq, "\n"); + put_device(ldev); + + spin_lock(&acpi_device_lock); + } + spin_unlock(&acpi_device_lock); + return 0; +} + +static void physical_device_enable_wakeup(struct acpi_device *adev) +{ + struct device *dev = acpi_get_physical_device(adev->handle); + + if (dev && device_can_wakeup(dev)) + device_set_wakeup_enable(dev, adev->wakeup.state.enabled); +} + +static ssize_t +acpi_system_write_wakeup_device(struct file *file, + const char __user * buffer, + size_t count, loff_t * ppos) +{ + struct list_head *node, *next; + char strbuf[5]; + char str[5] = ""; + int len = count; + struct acpi_device *found_dev = NULL; + + if (len > 4) + len = 4; + + if (copy_from_user(strbuf, buffer, len)) + return -EFAULT; + strbuf[len] = '\0'; + sscanf(strbuf, "%s", str); + + spin_lock(&acpi_device_lock); + list_for_each_safe(node, next, &acpi_wakeup_device_list) { + struct acpi_device *dev = + container_of(node, struct acpi_device, wakeup_list); + if (!dev->wakeup.flags.valid) + continue; + + if (!strncmp(dev->pnp.bus_id, str, 4)) { + dev->wakeup.state.enabled = + dev->wakeup.state.enabled ? 0 : 1; + found_dev = dev; + break; + } + } + if (found_dev) { + physical_device_enable_wakeup(found_dev); + list_for_each_safe(node, next, &acpi_wakeup_device_list) { + struct acpi_device *dev = container_of(node, + struct + acpi_device, + wakeup_list); + + if ((dev != found_dev) && + (dev->wakeup.gpe_number == + found_dev->wakeup.gpe_number) + && (dev->wakeup.gpe_device == + found_dev->wakeup.gpe_device)) { + printk(KERN_WARNING + "ACPI: '%s' and '%s' have the same GPE, " + "can't disable/enable one seperately\n", + dev->pnp.bus_id, found_dev->pnp.bus_id); + dev->wakeup.state.enabled = + found_dev->wakeup.state.enabled; + physical_device_enable_wakeup(dev); + } + } + } + spin_unlock(&acpi_device_lock); + return count; +} + +static int +acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_system_wakeup_device_seq_show, + PDE(inode)->data); +} + +static const struct file_operations acpi_system_wakeup_device_fops = { + .owner = THIS_MODULE, + .open = acpi_system_wakeup_device_open_fs, + .read = seq_read, + .write = acpi_system_write_wakeup_device, + .llseek = seq_lseek, + .release = single_release, +}; + +#ifdef CONFIG_ACPI_PROCFS +static const struct file_operations acpi_system_sleep_fops = { + .owner = THIS_MODULE, + .open = acpi_system_sleep_open_fs, + .read = seq_read, + .write = acpi_system_write_sleep, + .llseek = seq_lseek, + .release = single_release, +}; +#endif /* CONFIG_ACPI_PROCFS */ + +#ifdef HAVE_ACPI_LEGACY_ALARM +static const struct file_operations acpi_system_alarm_fops = { + .owner = THIS_MODULE, + .open = acpi_system_alarm_open_fs, + .read = seq_read, + .write = acpi_system_write_alarm, + .llseek = seq_lseek, + .release = single_release, +}; + +static u32 rtc_handler(void *context) +{ + acpi_clear_event(ACPI_EVENT_RTC); + acpi_disable_event(ACPI_EVENT_RTC, 0); + + return ACPI_INTERRUPT_HANDLED; +} +#endif /* HAVE_ACPI_LEGACY_ALARM */ + +static int __init acpi_sleep_proc_init(void) +{ + if (acpi_disabled) + return 0; + +#ifdef CONFIG_ACPI_PROCFS + /* 'sleep' [R/W] */ + proc_create("sleep", S_IFREG | S_IRUGO | S_IWUSR, + acpi_root_dir, &acpi_system_sleep_fops); +#endif /* CONFIG_ACPI_PROCFS */ + +#ifdef HAVE_ACPI_LEGACY_ALARM + /* 'alarm' [R/W] */ + proc_create("alarm", S_IFREG | S_IRUGO | S_IWUSR, + acpi_root_dir, &acpi_system_alarm_fops); + + acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); + /* + * Disable the RTC event after installing RTC handler. + * Only when RTC alarm is set will it be enabled. + */ + acpi_clear_event(ACPI_EVENT_RTC); + acpi_disable_event(ACPI_EVENT_RTC, 0); +#endif /* HAVE_ACPI_LEGACY_ALARM */ + + /* 'wakeup device' [R/W] */ + proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR, + acpi_root_dir, &acpi_system_wakeup_device_fops); + + return 0; +} + +late_initcall(acpi_sleep_proc_init); diff --git a/drivers/acpi/resources/Makefile b/drivers/acpi/resources/Makefile deleted file mode 100644 index 8de4f69dfa09..000000000000 --- a/drivers/acpi/resources/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -obj-y := rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \ - rscalc.o rsirq.o rsmemory.o rsutils.o - -obj-$(ACPI_FUTURE_USAGE) += rsdump.o - -EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c deleted file mode 100644 index b4aba3aebcb8..000000000000 --- a/drivers/acpi/resources/rsaddr.c +++ /dev/null @@ -1,381 +0,0 @@ -/******************************************************************************* - * - * Module Name: rsaddr - Address resource descriptors (16/32/64) - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rsaddr") - -/******************************************************************************* - * - * acpi_rs_convert_address16 - All WORD (16-bit) address resources - * - ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_convert_address16[5] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS16, - ACPI_RS_SIZE(struct acpi_resource_address16), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address16)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS16, - sizeof(struct aml_resource_address16), - 0}, - - /* Resource Type, General Flags, and Type-Specific Flags */ - - {ACPI_RSC_ADDRESS, 0, 0, 0}, - - /* - * These fields are contiguous in both the source and destination: - * Address Granularity - * Address Range Minimum - * Address Range Maximum - * Address Translation Offset - * Address Length - */ - {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.address16.granularity), - AML_OFFSET(address16.granularity), - 5}, - - /* Optional resource_source (Index and String) */ - - {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address16.resource_source), - 0, - sizeof(struct aml_resource_address16)} -}; - -/******************************************************************************* - * - * acpi_rs_convert_address32 - All DWORD (32-bit) address resources - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_convert_address32[5] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS32, - ACPI_RS_SIZE(struct acpi_resource_address32), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address32)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS32, - sizeof(struct aml_resource_address32), - 0}, - - /* Resource Type, General Flags, and Type-Specific Flags */ - - {ACPI_RSC_ADDRESS, 0, 0, 0}, - - /* - * These fields are contiguous in both the source and destination: - * Address Granularity - * Address Range Minimum - * Address Range Maximum - * Address Translation Offset - * Address Length - */ - {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.address32.granularity), - AML_OFFSET(address32.granularity), - 5}, - - /* Optional resource_source (Index and String) */ - - {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address32.resource_source), - 0, - sizeof(struct aml_resource_address32)} -}; - -/******************************************************************************* - * - * acpi_rs_convert_address64 - All QWORD (64-bit) address resources - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_convert_address64[5] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS64, - ACPI_RS_SIZE(struct acpi_resource_address64), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address64)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS64, - sizeof(struct aml_resource_address64), - 0}, - - /* Resource Type, General Flags, and Type-Specific Flags */ - - {ACPI_RSC_ADDRESS, 0, 0, 0}, - - /* - * These fields are contiguous in both the source and destination: - * Address Granularity - * Address Range Minimum - * Address Range Maximum - * Address Translation Offset - * Address Length - */ - {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.address64.granularity), - AML_OFFSET(address64.granularity), - 5}, - - /* Optional resource_source (Index and String) */ - - {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address64.resource_source), - 0, - sizeof(struct aml_resource_address64)} -}; - -/******************************************************************************* - * - * acpi_rs_convert_ext_address64 - All Extended (64-bit) address resources - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_convert_ext_address64[5] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64, - ACPI_RS_SIZE(struct acpi_resource_extended_address64), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_address64)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64, - sizeof(struct aml_resource_extended_address64), - 0}, - - /* Resource Type, General Flags, and Type-Specific Flags */ - - {ACPI_RSC_ADDRESS, 0, 0, 0}, - - /* Revision ID */ - - {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.ext_address64.revision_iD), - AML_OFFSET(ext_address64.revision_iD), - 1}, - /* - * These fields are contiguous in both the source and destination: - * Address Granularity - * Address Range Minimum - * Address Range Maximum - * Address Translation Offset - * Address Length - * Type-Specific Attribute - */ - {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.ext_address64.granularity), - AML_OFFSET(ext_address64.granularity), - 6} -}; - -/******************************************************************************* - * - * acpi_rs_convert_general_flags - Flags common to all address descriptors - * - ******************************************************************************/ - -static struct acpi_rsconvert_info acpi_rs_convert_general_flags[6] = { - {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.flags), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_general_flags)}, - - /* Resource Type (Memory, Io, bus_number, etc.) */ - - {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.address.resource_type), - AML_OFFSET(address.resource_type), - 1}, - - /* General Flags - Consume, Decode, min_fixed, max_fixed */ - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.producer_consumer), - AML_OFFSET(address.flags), - 0}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.decode), - AML_OFFSET(address.flags), - 1}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.min_address_fixed), - AML_OFFSET(address.flags), - 2}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.max_address_fixed), - AML_OFFSET(address.flags), - 3} -}; - -/******************************************************************************* - * - * acpi_rs_convert_mem_flags - Flags common to Memory address descriptors - * - ******************************************************************************/ - -static struct acpi_rsconvert_info acpi_rs_convert_mem_flags[5] = { - {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_mem_flags)}, - - /* Memory-specific flags */ - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.write_protect), - AML_OFFSET(address.specific_flags), - 0}, - - {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.caching), - AML_OFFSET(address.specific_flags), - 1}, - - {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.range_type), - AML_OFFSET(address.specific_flags), - 3}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.translation), - AML_OFFSET(address.specific_flags), - 5} -}; - -/******************************************************************************* - * - * acpi_rs_convert_io_flags - Flags common to I/O address descriptors - * - ******************************************************************************/ - -static struct acpi_rsconvert_info acpi_rs_convert_io_flags[4] = { - {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io_flags)}, - - /* I/O-specific flags */ - - {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.io.range_type), - AML_OFFSET(address.specific_flags), - 0}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.io.translation), - AML_OFFSET(address.specific_flags), - 4}, - - {ACPI_RSC_1BITFLAG, - ACPI_RS_OFFSET(data.address.info.io.translation_type), - AML_OFFSET(address.specific_flags), - 5} -}; - -/******************************************************************************* - * - * FUNCTION: acpi_rs_get_address_common - * - * PARAMETERS: Resource - Pointer to the internal resource struct - * Aml - Pointer to the AML resource descriptor - * - * RETURN: TRUE if the resource_type field is OK, FALSE otherwise - * - * DESCRIPTION: Convert common flag fields from a raw AML resource descriptor - * to an internal resource descriptor - * - ******************************************************************************/ - -u8 -acpi_rs_get_address_common(struct acpi_resource *resource, - union aml_resource *aml) -{ - ACPI_FUNCTION_ENTRY(); - - /* Validate the Resource Type */ - - if ((aml->address.resource_type > 2) - && (aml->address.resource_type < 0xC0)) { - return (FALSE); - } - - /* Get the Resource Type and General Flags */ - - (void)acpi_rs_convert_aml_to_resource(resource, aml, - acpi_rs_convert_general_flags); - - /* Get the Type-Specific Flags (Memory and I/O descriptors only) */ - - if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) { - (void)acpi_rs_convert_aml_to_resource(resource, aml, - acpi_rs_convert_mem_flags); - } else if (resource->data.address.resource_type == ACPI_IO_RANGE) { - (void)acpi_rs_convert_aml_to_resource(resource, aml, - acpi_rs_convert_io_flags); - } else { - /* Generic resource type, just grab the type_specific byte */ - - resource->data.address.info.type_specific = - aml->address.specific_flags; - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_set_address_common - * - * PARAMETERS: Aml - Pointer to the AML resource descriptor - * Resource - Pointer to the internal resource struct - * - * RETURN: None - * - * DESCRIPTION: Convert common flag fields from a resource descriptor to an - * AML descriptor - * - ******************************************************************************/ - -void -acpi_rs_set_address_common(union aml_resource *aml, - struct acpi_resource *resource) -{ - ACPI_FUNCTION_ENTRY(); - - /* Set the Resource Type and General Flags */ - - (void)acpi_rs_convert_resource_to_aml(resource, aml, - acpi_rs_convert_general_flags); - - /* Set the Type-Specific Flags (Memory and I/O descriptors only) */ - - if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) { - (void)acpi_rs_convert_resource_to_aml(resource, aml, - acpi_rs_convert_mem_flags); - } else if (resource->data.address.resource_type == ACPI_IO_RANGE) { - (void)acpi_rs_convert_resource_to_aml(resource, aml, - acpi_rs_convert_io_flags); - } else { - /* Generic resource type, just copy the type_specific byte */ - - aml->address.specific_flags = - resource->data.address.info.type_specific; - } -} diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c deleted file mode 100644 index 4f2b186fe302..000000000000 --- a/drivers/acpi/resources/rscalc.c +++ /dev/null @@ -1,618 +0,0 @@ -/******************************************************************************* - * - * Module Name: rscalc - Calculate stream and list lengths - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rscalc") - -/* Local prototypes */ -static u8 acpi_rs_count_set_bits(u16 bit_field); - -static acpi_rs_length -acpi_rs_struct_option_length(struct acpi_resource_source *resource_source); - -static u32 -acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length); - -/******************************************************************************* - * - * FUNCTION: acpi_rs_count_set_bits - * - * PARAMETERS: bit_field - Field in which to count bits - * - * RETURN: Number of bits set within the field - * - * DESCRIPTION: Count the number of bits set in a resource field. Used for - * (Short descriptor) interrupt and DMA lists. - * - ******************************************************************************/ - -static u8 acpi_rs_count_set_bits(u16 bit_field) -{ - u8 bits_set; - - ACPI_FUNCTION_ENTRY(); - - for (bits_set = 0; bit_field; bits_set++) { - - /* Zero the least significant bit that is set */ - - bit_field &= (u16) (bit_field - 1); - } - - return bits_set; -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_struct_option_length - * - * PARAMETERS: resource_source - Pointer to optional descriptor field - * - * RETURN: Status - * - * DESCRIPTION: Common code to handle optional resource_source_index and - * resource_source fields in some Large descriptors. Used during - * list-to-stream conversion - * - ******************************************************************************/ - -static acpi_rs_length -acpi_rs_struct_option_length(struct acpi_resource_source *resource_source) -{ - ACPI_FUNCTION_ENTRY(); - - /* - * If the resource_source string is valid, return the size of the string - * (string_length includes the NULL terminator) plus the size of the - * resource_source_index (1). - */ - if (resource_source->string_ptr) { - return ((acpi_rs_length) (resource_source->string_length + 1)); - } - - return (0); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_stream_option_length - * - * PARAMETERS: resource_length - Length from the resource header - * minimum_total_length - Minimum length of this resource, before - * any optional fields. Includes header size - * - * RETURN: Length of optional string (0 if no string present) - * - * DESCRIPTION: Common code to handle optional resource_source_index and - * resource_source fields in some Large descriptors. Used during - * stream-to-list conversion - * - ******************************************************************************/ - -static u32 -acpi_rs_stream_option_length(u32 resource_length, - u32 minimum_aml_resource_length) -{ - u32 string_length = 0; - - ACPI_FUNCTION_ENTRY(); - - /* - * The resource_source_index and resource_source are optional elements of some - * Large-type resource descriptors. - */ - - /* - * If the length of the actual resource descriptor is greater than the ACPI - * spec-defined minimum length, it means that a resource_source_index exists - * and is followed by a (required) null terminated string. The string length - * (including the null terminator) is the resource length minus the minimum - * length, minus one byte for the resource_source_index itself. - */ - if (resource_length > minimum_aml_resource_length) { - - /* Compute the length of the optional string */ - - string_length = - resource_length - minimum_aml_resource_length - 1; - } - - /* - * Round the length up to a multiple of the native word in order to - * guarantee that the entire resource descriptor is native word aligned - */ - return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length)); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_get_aml_length - * - * PARAMETERS: Resource - Pointer to the resource linked list - * size_needed - Where the required size is returned - * - * RETURN: Status - * - * DESCRIPTION: Takes a linked list of internal resource descriptors and - * calculates the size buffer needed to hold the corresponding - * external resource byte stream. - * - ******************************************************************************/ - -acpi_status -acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) -{ - acpi_size aml_size_needed = 0; - acpi_rs_length total_size; - - ACPI_FUNCTION_TRACE(rs_get_aml_length); - - /* Traverse entire list of internal resource descriptors */ - - while (resource) { - - /* Validate the descriptor type */ - - if (resource->type > ACPI_RESOURCE_TYPE_MAX) { - return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); - } - - /* Get the base size of the (external stream) resource descriptor */ - - total_size = acpi_gbl_aml_resource_sizes[resource->type]; - - /* - * Augment the base size for descriptors with optional and/or - * variable-length fields - */ - switch (resource->type) { - case ACPI_RESOURCE_TYPE_IRQ: - - /* Length can be 3 or 2 */ - - if (resource->data.irq.descriptor_length == 2) { - total_size--; - } - break; - - case ACPI_RESOURCE_TYPE_START_DEPENDENT: - - /* Length can be 1 or 0 */ - - if (resource->data.irq.descriptor_length == 0) { - total_size--; - } - break; - - case ACPI_RESOURCE_TYPE_VENDOR: - /* - * Vendor Defined Resource: - * For a Vendor Specific resource, if the Length is between 1 and 7 - * it will be created as a Small Resource data type, otherwise it - * is a Large Resource data type. - */ - if (resource->data.vendor.byte_length > 7) { - - /* Base size of a Large resource descriptor */ - - total_size = - sizeof(struct aml_resource_large_header); - } - - /* Add the size of the vendor-specific data */ - - total_size = (acpi_rs_length) - (total_size + resource->data.vendor.byte_length); - break; - - case ACPI_RESOURCE_TYPE_END_TAG: - /* - * End Tag: - * We are done -- return the accumulated total size. - */ - *size_needed = aml_size_needed + total_size; - - /* Normal exit */ - - return_ACPI_STATUS(AE_OK); - - case ACPI_RESOURCE_TYPE_ADDRESS16: - /* - * 16-Bit Address Resource: - * Add the size of the optional resource_source info - */ - total_size = (acpi_rs_length) - (total_size + - acpi_rs_struct_option_length(&resource->data. - address16. - resource_source)); - break; - - case ACPI_RESOURCE_TYPE_ADDRESS32: - /* - * 32-Bit Address Resource: - * Add the size of the optional resource_source info - */ - total_size = (acpi_rs_length) - (total_size + - acpi_rs_struct_option_length(&resource->data. - address32. - resource_source)); - break; - - case ACPI_RESOURCE_TYPE_ADDRESS64: - /* - * 64-Bit Address Resource: - * Add the size of the optional resource_source info - */ - total_size = (acpi_rs_length) - (total_size + - acpi_rs_struct_option_length(&resource->data. - address64. - resource_source)); - break; - - case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - /* - * Extended IRQ Resource: - * Add the size of each additional optional interrupt beyond the - * required 1 (4 bytes for each u32 interrupt number) - */ - total_size = (acpi_rs_length) - (total_size + - ((resource->data.extended_irq.interrupt_count - - 1) * 4) + - /* Add the size of the optional resource_source info */ - acpi_rs_struct_option_length(&resource->data. - extended_irq. - resource_source)); - break; - - default: - break; - } - - /* Update the total */ - - aml_size_needed += total_size; - - /* Point to the next object */ - - resource = - ACPI_ADD_PTR(struct acpi_resource, resource, - resource->length); - } - - /* Did not find an end_tag resource descriptor */ - - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_get_list_length - * - * PARAMETERS: aml_buffer - Pointer to the resource byte stream - * aml_buffer_length - Size of aml_buffer - * size_needed - Where the size needed is returned - * - * RETURN: Status - * - * DESCRIPTION: Takes an external resource byte stream and calculates the size - * buffer needed to hold the corresponding internal resource - * descriptor linked list. - * - ******************************************************************************/ - -acpi_status -acpi_rs_get_list_length(u8 * aml_buffer, - u32 aml_buffer_length, acpi_size * size_needed) -{ - acpi_status status; - u8 *end_aml; - u8 *buffer; - u32 buffer_size; - u16 temp16; - u16 resource_length; - u32 extra_struct_bytes; - u8 resource_index; - u8 minimum_aml_resource_length; - - ACPI_FUNCTION_TRACE(rs_get_list_length); - - *size_needed = 0; - end_aml = aml_buffer + aml_buffer_length; - - /* Walk the list of AML resource descriptors */ - - while (aml_buffer < end_aml) { - - /* Validate the Resource Type and Resource Length */ - - status = acpi_ut_validate_resource(aml_buffer, &resource_index); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get the resource length and base (minimum) AML size */ - - resource_length = acpi_ut_get_resource_length(aml_buffer); - minimum_aml_resource_length = - acpi_gbl_resource_aml_sizes[resource_index]; - - /* - * Augment the size for descriptors with optional - * and/or variable length fields - */ - extra_struct_bytes = 0; - buffer = - aml_buffer + acpi_ut_get_resource_header_length(aml_buffer); - - switch (acpi_ut_get_resource_type(aml_buffer)) { - case ACPI_RESOURCE_NAME_IRQ: - /* - * IRQ Resource: - * Get the number of bits set in the 16-bit IRQ mask - */ - ACPI_MOVE_16_TO_16(&temp16, buffer); - extra_struct_bytes = acpi_rs_count_set_bits(temp16); - break; - - case ACPI_RESOURCE_NAME_DMA: - /* - * DMA Resource: - * Get the number of bits set in the 8-bit DMA mask - */ - extra_struct_bytes = acpi_rs_count_set_bits(*buffer); - break; - - case ACPI_RESOURCE_NAME_VENDOR_SMALL: - case ACPI_RESOURCE_NAME_VENDOR_LARGE: - /* - * Vendor Resource: - * Get the number of vendor data bytes - */ - extra_struct_bytes = resource_length; - break; - - case ACPI_RESOURCE_NAME_END_TAG: - /* - * End Tag: - * This is the normal exit, add size of end_tag - */ - *size_needed += ACPI_RS_SIZE_MIN; - return_ACPI_STATUS(AE_OK); - - case ACPI_RESOURCE_NAME_ADDRESS32: - case ACPI_RESOURCE_NAME_ADDRESS16: - case ACPI_RESOURCE_NAME_ADDRESS64: - /* - * Address Resource: - * Add the size of the optional resource_source - */ - extra_struct_bytes = - acpi_rs_stream_option_length(resource_length, - minimum_aml_resource_length); - break; - - case ACPI_RESOURCE_NAME_EXTENDED_IRQ: - /* - * Extended IRQ Resource: - * Using the interrupt_table_length, add 4 bytes for each additional - * interrupt. Note: at least one interrupt is required and is - * included in the minimum descriptor size (reason for the -1) - */ - extra_struct_bytes = (buffer[1] - 1) * sizeof(u32); - - /* Add the size of the optional resource_source */ - - extra_struct_bytes += - acpi_rs_stream_option_length(resource_length - - extra_struct_bytes, - minimum_aml_resource_length); - break; - - default: - break; - } - - /* - * Update the required buffer size for the internal descriptor structs - * - * Important: Round the size up for the appropriate alignment. This - * is a requirement on IA64. - */ - buffer_size = acpi_gbl_resource_struct_sizes[resource_index] + - extra_struct_bytes; - buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size); - - *size_needed += buffer_size; - - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Type %.2X, AmlLength %.2X InternalLength %.2X\n", - acpi_ut_get_resource_type(aml_buffer), - acpi_ut_get_descriptor_length(aml_buffer), - buffer_size)); - - /* - * Point to the next resource within the AML stream using the length - * contained in the resource descriptor header - */ - aml_buffer += acpi_ut_get_descriptor_length(aml_buffer); - } - - /* Did not find an end_tag resource descriptor */ - - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_get_pci_routing_table_length - * - * PARAMETERS: package_object - Pointer to the package object - * buffer_size_needed - u32 pointer of the size buffer - * needed to properly return the - * parsed data - * - * RETURN: Status - * - * DESCRIPTION: Given a package representing a PCI routing table, this - * calculates the size of the corresponding linked list of - * descriptions. - * - ******************************************************************************/ - -acpi_status -acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, - acpi_size * buffer_size_needed) -{ - u32 number_of_elements; - acpi_size temp_size_needed = 0; - union acpi_operand_object **top_object_list; - u32 index; - union acpi_operand_object *package_element; - union acpi_operand_object **sub_object_list; - u8 name_found; - u32 table_index; - - ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length); - - number_of_elements = package_object->package.count; - - /* - * Calculate the size of the return buffer. - * The base size is the number of elements * the sizes of the - * structures. Additional space for the strings is added below. - * The minus one is to subtract the size of the u8 Source[1] - * member because it is added below. - * - * But each PRT_ENTRY structure has a pointer to a string and - * the size of that string must be found. - */ - top_object_list = package_object->package.elements; - - for (index = 0; index < number_of_elements; index++) { - - /* Dereference the sub-package */ - - package_element = *top_object_list; - - /* - * The sub_object_list will now point to an array of the - * four IRQ elements: Address, Pin, Source and source_index - */ - sub_object_list = package_element->package.elements; - - /* Scan the irq_table_elements for the Source Name String */ - - name_found = FALSE; - - for (table_index = 0; table_index < 4 && !name_found; - table_index++) { - if (*sub_object_list && /* Null object allowed */ - ((ACPI_TYPE_STRING == - ACPI_GET_OBJECT_TYPE(*sub_object_list)) || - ((ACPI_TYPE_LOCAL_REFERENCE == - ACPI_GET_OBJECT_TYPE(*sub_object_list)) && - ((*sub_object_list)->reference.class == - ACPI_REFCLASS_NAME)))) { - name_found = TRUE; - } else { - /* Look at the next element */ - - sub_object_list++; - } - } - - temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4); - - /* Was a String type found? */ - - if (name_found) { - if (ACPI_GET_OBJECT_TYPE(*sub_object_list) == - ACPI_TYPE_STRING) { - /* - * The length String.Length field does not include the - * terminating NULL, add 1 - */ - temp_size_needed += ((acpi_size) - (*sub_object_list)->string. - length + 1); - } else { - temp_size_needed += - acpi_ns_get_pathname_length((*sub_object_list)->reference.node); - if (!temp_size_needed) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - } - } else { - /* - * If no name was found, then this is a NULL, which is - * translated as a u32 zero. - */ - temp_size_needed += sizeof(u32); - } - - /* Round up the size since each element must be aligned */ - - temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed); - - /* Point to the next union acpi_operand_object */ - - top_object_list++; - } - - /* - * Add an extra element to the end of the list, essentially a - * NULL terminator - */ - *buffer_size_needed = - temp_size_needed + sizeof(struct acpi_pci_routing_table); - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c deleted file mode 100644 index 3ca606974d51..000000000000 --- a/drivers/acpi/resources/rscreate.c +++ /dev/null @@ -1,468 +0,0 @@ -/******************************************************************************* - * - * Module Name: rscreate - Create resource lists/tables - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rscreate") - -/******************************************************************************* - * - * FUNCTION: acpi_rs_create_resource_list - * - * PARAMETERS: aml_buffer - Pointer to the resource byte stream - * output_buffer - Pointer to the user's buffer - * - * RETURN: Status: AE_OK if okay, else a valid acpi_status code - * If output_buffer is not large enough, output_buffer_length - * indicates how large output_buffer should be, else it - * indicates how may u8 elements of output_buffer are valid. - * - * DESCRIPTION: Takes the byte stream returned from a _CRS, _PRS control method - * execution and parses the stream to create a linked list - * of device resources. - * - ******************************************************************************/ -acpi_status -acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, - struct acpi_buffer *output_buffer) -{ - - acpi_status status; - u8 *aml_start; - acpi_size list_size_needed = 0; - u32 aml_buffer_length; - void *resource; - - ACPI_FUNCTION_TRACE(rs_create_resource_list); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlBuffer = %p\n", aml_buffer)); - - /* Params already validated, so we don't re-validate here */ - - aml_buffer_length = aml_buffer->buffer.length; - aml_start = aml_buffer->buffer.pointer; - - /* - * Pass the aml_buffer into a module that can calculate - * the buffer size needed for the linked list - */ - status = acpi_rs_get_list_length(aml_start, aml_buffer_length, - &list_size_needed); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X ListSizeNeeded=%X\n", - status, (u32) list_size_needed)); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Validate/Allocate/Clear caller buffer */ - - status = acpi_ut_initialize_buffer(output_buffer, list_size_needed); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Do the conversion */ - - resource = output_buffer->pointer; - status = acpi_ut_walk_aml_resources(aml_start, aml_buffer_length, - acpi_rs_convert_aml_to_resources, - &resource); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", - output_buffer->pointer, (u32) output_buffer->length)); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_create_pci_routing_table - * - * PARAMETERS: package_object - Pointer to an union acpi_operand_object - * package - * output_buffer - Pointer to the user's buffer - * - * RETURN: Status AE_OK if okay, else a valid acpi_status code. - * If the output_buffer is too small, the error will be - * AE_BUFFER_OVERFLOW and output_buffer->Length will point - * to the size buffer needed. - * - * DESCRIPTION: Takes the union acpi_operand_object package and creates a - * linked list of PCI interrupt descriptions - * - * NOTE: It is the caller's responsibility to ensure that the start of the - * output buffer is aligned properly (if necessary). - * - ******************************************************************************/ - -acpi_status -acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, - struct acpi_buffer *output_buffer) -{ - u8 *buffer; - union acpi_operand_object **top_object_list; - union acpi_operand_object **sub_object_list; - union acpi_operand_object *obj_desc; - acpi_size buffer_size_needed = 0; - u32 number_of_elements; - u32 index; - struct acpi_pci_routing_table *user_prt; - struct acpi_namespace_node *node; - acpi_status status; - struct acpi_buffer path_buffer; - - ACPI_FUNCTION_TRACE(rs_create_pci_routing_table); - - /* Params already validated, so we don't re-validate here */ - - /* Get the required buffer length */ - - status = acpi_rs_get_pci_routing_table_length(package_object, - &buffer_size_needed); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "BufferSizeNeeded = %X\n", - (u32) buffer_size_needed)); - - /* Validate/Allocate/Clear caller buffer */ - - status = acpi_ut_initialize_buffer(output_buffer, buffer_size_needed); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Loop through the ACPI_INTERNAL_OBJECTS - Each object should be a - * package that in turn contains an acpi_integer Address, a u8 Pin, - * a Name, and a u8 source_index. - */ - top_object_list = package_object->package.elements; - number_of_elements = package_object->package.count; - buffer = output_buffer->pointer; - user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer); - - for (index = 0; index < number_of_elements; index++) { - int source_name_index = 2; - int source_index_index = 3; - - /* - * Point user_prt past this current structure - * - * NOTE: On the first iteration, user_prt->Length will - * be zero because we cleared the return buffer earlier - */ - buffer += user_prt->length; - user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer); - - /* - * Fill in the Length field with the information we have at this point. - * The minus four is to subtract the size of the u8 Source[4] member - * because it is added below. - */ - user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4); - - /* Each element of the top-level package must also be a package */ - - if (ACPI_GET_OBJECT_TYPE(*top_object_list) != ACPI_TYPE_PACKAGE) { - ACPI_ERROR((AE_INFO, - "(PRT[%X]) Need sub-package, found %s", - index, - acpi_ut_get_object_type_name - (*top_object_list))); - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* Each sub-package must be of length 4 */ - - if ((*top_object_list)->package.count != 4) { - ACPI_ERROR((AE_INFO, - "(PRT[%X]) Need package of length 4, found length %d", - index, (*top_object_list)->package.count)); - return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT); - } - - /* - * Dereference the sub-package. - * The sub_object_list will now point to an array of the four IRQ - * elements: [Address, Pin, Source, source_index] - */ - sub_object_list = (*top_object_list)->package.elements; - - /* 1) First subobject: Dereference the PRT.Address */ - - obj_desc = sub_object_list[0]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, - "(PRT[%X].Address) Need Integer, found %s", - index, - acpi_ut_get_object_type_name(obj_desc))); - return_ACPI_STATUS(AE_BAD_DATA); - } - - user_prt->address = obj_desc->integer.value; - - /* 2) Second subobject: Dereference the PRT.Pin */ - - obj_desc = sub_object_list[1]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, - "(PRT[%X].Pin) Need Integer, found %s", - index, - acpi_ut_get_object_type_name(obj_desc))); - return_ACPI_STATUS(AE_BAD_DATA); - } - - /* - * If BIOS erroneously reversed the _PRT source_name and source_index, - * then reverse them back. - */ - if (ACPI_GET_OBJECT_TYPE(sub_object_list[3]) != - ACPI_TYPE_INTEGER) { - if (acpi_gbl_enable_interpreter_slack) { - source_name_index = 3; - source_index_index = 2; - printk(KERN_WARNING - "ACPI: Handling Garbled _PRT entry\n"); - } else { - ACPI_ERROR((AE_INFO, - "(PRT[%X].source_index) Need Integer, found %s", - index, - acpi_ut_get_object_type_name - (sub_object_list[3]))); - return_ACPI_STATUS(AE_BAD_DATA); - } - } - - user_prt->pin = (u32) obj_desc->integer.value; - - /* - * If the BIOS has erroneously reversed the _PRT source_name (index 2) - * and the source_index (index 3), fix it. _PRT is important enough to - * workaround this BIOS error. This also provides compatibility with - * other ACPI implementations. - */ - obj_desc = sub_object_list[3]; - if (!obj_desc - || (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { - sub_object_list[3] = sub_object_list[2]; - sub_object_list[2] = obj_desc; - - ACPI_WARNING((AE_INFO, - "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed", - index)); - } - - /* - * 3) Third subobject: Dereference the PRT.source_name - * The name may be unresolved (slack mode), so allow a null object - */ - obj_desc = sub_object_list[source_name_index]; - if (obj_desc) { - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_LOCAL_REFERENCE: - - if (obj_desc->reference.class != - ACPI_REFCLASS_NAME) { - ACPI_ERROR((AE_INFO, - "(PRT[%X].Source) Need name, found Reference Class %X", - index, - obj_desc->reference.class)); - return_ACPI_STATUS(AE_BAD_DATA); - } - - node = obj_desc->reference.node; - - /* Use *remaining* length of the buffer as max for pathname */ - - path_buffer.length = output_buffer->length - - (u32) ((u8 *) user_prt->source - - (u8 *) output_buffer->pointer); - path_buffer.pointer = user_prt->source; - - status = - acpi_ns_handle_to_pathname((acpi_handle) - node, - &path_buffer); - - /* +1 to include null terminator */ - - user_prt->length += - (u32) ACPI_STRLEN(user_prt->source) + 1; - break; - - case ACPI_TYPE_STRING: - - ACPI_STRCPY(user_prt->source, - obj_desc->string.pointer); - - /* - * Add to the Length field the length of the string - * (add 1 for terminator) - */ - user_prt->length += obj_desc->string.length + 1; - break; - - case ACPI_TYPE_INTEGER: - /* - * If this is a number, then the Source Name is NULL, since the - * entire buffer was zeroed out, we can leave this alone. - * - * Add to the Length field the length of the u32 NULL - */ - user_prt->length += sizeof(u32); - break; - - default: - - ACPI_ERROR((AE_INFO, - "(PRT[%X].Source) Need Ref/String/Integer, found %s", - index, - acpi_ut_get_object_type_name - (obj_desc))); - return_ACPI_STATUS(AE_BAD_DATA); - } - } - - /* Now align the current length */ - - user_prt->length = - (u32) ACPI_ROUND_UP_TO_64BIT(user_prt->length); - - /* 4) Fourth subobject: Dereference the PRT.source_index */ - - obj_desc = sub_object_list[source_index_index]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, - "(PRT[%X].SourceIndex) Need Integer, found %s", - index, - acpi_ut_get_object_type_name(obj_desc))); - return_ACPI_STATUS(AE_BAD_DATA); - } - - user_prt->source_index = (u32) obj_desc->integer.value; - - /* Point to the next union acpi_operand_object in the top level package */ - - top_object_list++; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", - output_buffer->pointer, (u32) output_buffer->length)); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_create_aml_resources - * - * PARAMETERS: linked_list_buffer - Pointer to the resource linked list - * output_buffer - Pointer to the user's buffer - * - * RETURN: Status AE_OK if okay, else a valid acpi_status code. - * If the output_buffer is too small, the error will be - * AE_BUFFER_OVERFLOW and output_buffer->Length will point - * to the size buffer needed. - * - * DESCRIPTION: Takes the linked list of device resources and - * creates a bytestream to be used as input for the - * _SRS control method. - * - ******************************************************************************/ - -acpi_status -acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, - struct acpi_buffer *output_buffer) -{ - acpi_status status; - acpi_size aml_size_needed = 0; - - ACPI_FUNCTION_TRACE(rs_create_aml_resources); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "LinkedListBuffer = %p\n", - linked_list_buffer)); - - /* - * Params already validated, so we don't re-validate here - * - * Pass the linked_list_buffer into a module that calculates - * the buffer size needed for the byte stream. - */ - status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n", - (u32) aml_size_needed, - acpi_format_exception(status))); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Validate/Allocate/Clear caller buffer */ - - status = acpi_ut_initialize_buffer(output_buffer, aml_size_needed); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Do the conversion */ - - status = - acpi_rs_convert_resources_to_aml(linked_list_buffer, - aml_size_needed, - output_buffer->pointer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", - output_buffer->pointer, (u32) output_buffer->length)); - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c deleted file mode 100644 index 936a59be39fa..000000000000 --- a/drivers/acpi/resources/rsdump.c +++ /dev/null @@ -1,771 +0,0 @@ -/******************************************************************************* - * - * Module Name: rsdump - Functions to display the resource structures. - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rsdump") -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) -/* Local prototypes */ -static void acpi_rs_out_string(char *title, char *value); - -static void acpi_rs_out_integer8(char *title, u8 value); - -static void acpi_rs_out_integer16(char *title, u16 value); - -static void acpi_rs_out_integer32(char *title, u32 value); - -static void acpi_rs_out_integer64(char *title, u64 value); - -static void acpi_rs_out_title(char *title); - -static void acpi_rs_dump_byte_list(u16 length, u8 * data); - -static void acpi_rs_dump_dword_list(u8 length, u32 * data); - -static void acpi_rs_dump_short_byte_list(u8 length, u8 * data); - -static void -acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source); - -static void acpi_rs_dump_address_common(union acpi_resource_data *resource); - -static void -acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table); - -#define ACPI_RSD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_resource_data,f) -#define ACPI_PRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f) -#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_rsdump_info)) - -/******************************************************************************* - * - * Resource Descriptor info tables - * - * Note: The first table entry must be a Title or Literal and must contain - * the table length (number of table entries) - * - ******************************************************************************/ - -struct acpi_rsdump_info acpi_rs_dump_irq[7] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length), - "Descriptor Length", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", - acpi_gbl_he_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", - acpi_gbl_ll_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing", - acpi_gbl_shr_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count), - "Interrupt Count", NULL}, - {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]), - "Interrupt List", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_dma[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed", - acpi_gbl_typ_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering", - acpi_gbl_bm_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type", - acpi_gbl_siz_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count", - NULL}, - {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), - "Start-Dependent-Functions", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length), - "Descriptor Length", NULL}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), - "Compatibility Priority", acpi_gbl_config_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), - "Performance/Robustness", acpi_gbl_config_decode} -}; - -struct acpi_rsdump_info acpi_rs_dump_end_dpf[1] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_dpf), - "End-Dependent-Functions", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_io[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io), "I/O", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(io.io_decode), "Address Decoding", - acpi_gbl_io_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.minimum), "Address Minimum", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.maximum), "Address Maximum", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.alignment), "Alignment", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.address_length), "Address Length", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_fixed_io[3] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_io), - "Fixed I/O", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_io.address), "Address", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_io.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_vendor[3] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_vendor), - "Vendor Specific", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(vendor.byte_length), "Length", NULL}, - {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET(vendor.byte_data[0]), "Vendor Data", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_memory24[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24), - "24-Bit Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.alignment), "Alignment", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_memory32[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32), - "32-Bit Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.alignment), "Alignment", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32), - "32-Bit Fixed Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address16[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16), - "16-Bit WORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address32[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32), - "32-Bit DWORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address64[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64), - "64-Bit QWORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64), - "64-Bit Extended Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity), - "Granularity", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum), - "Address Minimum", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum), - "Address Maximum", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length), - "Address Length", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific), - "Type-Specific Attribute", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_irq), - "Extended IRQ", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer), - "Type", acpi_gbl_consume_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering), - "Triggering", acpi_gbl_he_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity", - acpi_gbl_ll_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing", - acpi_gbl_shr_decode}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL, - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count), - "Interrupt Count", NULL}, - {ACPI_RSD_DWORDLIST, ACPI_RSD_OFFSET(extended_irq.interrupts[0]), - "Interrupt List", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_generic_reg), - "Generic Register", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.space_id), "Space ID", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_width), "Bit Width", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_offset), "Bit Offset", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.access_size), - "Access Size", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL} -}; - -/* - * Tables used for common address descriptor flag fields - */ -static struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_general_flags), NULL, - NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer), - "Consumer/Producer", acpi_gbl_consume_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode", - acpi_gbl_dec_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed), - "Min Relocatability", acpi_gbl_min_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed), - "Max Relocatability", acpi_gbl_max_decode} -}; - -static struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = { - {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags), - "Resource Type", (void *)"Memory Range"}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching), - "Caching", acpi_gbl_mem_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type), - "Range Type", acpi_gbl_mtp_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation), - "Translation", acpi_gbl_ttp_decode} -}; - -static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = { - {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags), - "Resource Type", (void *)"I/O Range"}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type), - "Range Type", acpi_gbl_rng_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation), - "Translation", acpi_gbl_ttp_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type), - "Translation Type", acpi_gbl_trs_decode} -}; - -/* - * Table used to dump _PRT contents - */ -static struct acpi_rsdump_info acpi_rs_dump_prt[5] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_prt), NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_PRT_OFFSET(address), "Address", NULL}, - {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(pin), "Pin", NULL}, - {ACPI_RSD_STRING, ACPI_PRT_OFFSET(source[0]), "Source", NULL}, - {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(source_index), "Source Index", NULL} -}; - -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_descriptor - * - * PARAMETERS: Resource - * - * RETURN: None - * - * DESCRIPTION: - * - ******************************************************************************/ - -static void -acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) -{ - u8 *target = NULL; - u8 *previous_target; - char *name; - u8 count; - - /* First table entry must contain the table length (# of table entries) */ - - count = table->offset; - - while (count) { - previous_target = target; - target = ACPI_ADD_PTR(u8, resource, table->offset); - name = table->name; - - switch (table->opcode) { - case ACPI_RSD_TITLE: - /* - * Optional resource title - */ - if (table->name) { - acpi_os_printf("%s Resource\n", name); - } - break; - - /* Strings */ - - case ACPI_RSD_LITERAL: - acpi_rs_out_string(name, - ACPI_CAST_PTR(char, table->pointer)); - break; - - case ACPI_RSD_STRING: - acpi_rs_out_string(name, ACPI_CAST_PTR(char, target)); - break; - - /* Data items, 8/16/32/64 bit */ - - case ACPI_RSD_UINT8: - acpi_rs_out_integer8(name, ACPI_GET8(target)); - break; - - case ACPI_RSD_UINT16: - acpi_rs_out_integer16(name, ACPI_GET16(target)); - break; - - case ACPI_RSD_UINT32: - acpi_rs_out_integer32(name, ACPI_GET32(target)); - break; - - case ACPI_RSD_UINT64: - acpi_rs_out_integer64(name, ACPI_GET64(target)); - break; - - /* Flags: 1-bit and 2-bit flags supported */ - - case ACPI_RSD_1BITFLAG: - acpi_rs_out_string(name, ACPI_CAST_PTR(char, - table-> - pointer[*target & - 0x01])); - break; - - case ACPI_RSD_2BITFLAG: - acpi_rs_out_string(name, ACPI_CAST_PTR(char, - table-> - pointer[*target & - 0x03])); - break; - - case ACPI_RSD_SHORTLIST: - /* - * Short byte list (single line output) for DMA and IRQ resources - * Note: The list length is obtained from the previous table entry - */ - if (previous_target) { - acpi_rs_out_title(name); - acpi_rs_dump_short_byte_list(*previous_target, - target); - } - break; - - case ACPI_RSD_LONGLIST: - /* - * Long byte list for Vendor resource data - * Note: The list length is obtained from the previous table entry - */ - if (previous_target) { - acpi_rs_dump_byte_list(ACPI_GET16 - (previous_target), - target); - } - break; - - case ACPI_RSD_DWORDLIST: - /* - * Dword list for Extended Interrupt resources - * Note: The list length is obtained from the previous table entry - */ - if (previous_target) { - acpi_rs_dump_dword_list(*previous_target, - ACPI_CAST_PTR(u32, - target)); - } - break; - - case ACPI_RSD_ADDRESS: - /* - * Common flags for all Address resources - */ - acpi_rs_dump_address_common(ACPI_CAST_PTR - (union acpi_resource_data, - target)); - break; - - case ACPI_RSD_SOURCE: - /* - * Optional resource_source for Address resources - */ - acpi_rs_dump_resource_source(ACPI_CAST_PTR(struct - acpi_resource_source, - target)); - break; - - default: - acpi_os_printf("**** Invalid table opcode [%X] ****\n", - table->opcode); - return; - } - - table++; - count--; - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_resource_source - * - * PARAMETERS: resource_source - Pointer to a Resource Source struct - * - * RETURN: None - * - * DESCRIPTION: Common routine for dumping the optional resource_source and the - * corresponding resource_source_index. - * - ******************************************************************************/ - -static void -acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source) -{ - ACPI_FUNCTION_ENTRY(); - - if (resource_source->index == 0xFF) { - return; - } - - acpi_rs_out_integer8("Resource Source Index", resource_source->index); - - acpi_rs_out_string("Resource Source", - resource_source->string_ptr ? - resource_source->string_ptr : "[Not Specified]"); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_address_common - * - * PARAMETERS: Resource - Pointer to an internal resource descriptor - * - * RETURN: None - * - * DESCRIPTION: Dump the fields that are common to all Address resource - * descriptors - * - ******************************************************************************/ - -static void acpi_rs_dump_address_common(union acpi_resource_data *resource) -{ - ACPI_FUNCTION_ENTRY(); - - /* Decode the type-specific flags */ - - switch (resource->address.resource_type) { - case ACPI_MEMORY_RANGE: - - acpi_rs_dump_descriptor(resource, acpi_rs_dump_memory_flags); - break; - - case ACPI_IO_RANGE: - - acpi_rs_dump_descriptor(resource, acpi_rs_dump_io_flags); - break; - - case ACPI_BUS_NUMBER_RANGE: - - acpi_rs_out_string("Resource Type", "Bus Number Range"); - break; - - default: - - acpi_rs_out_integer8("Resource Type", - (u8) resource->address.resource_type); - break; - } - - /* Decode the general flags */ - - acpi_rs_dump_descriptor(resource, acpi_rs_dump_general_flags); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_resource_list - * - * PARAMETERS: resource_list - Pointer to a resource descriptor list - * - * RETURN: None - * - * DESCRIPTION: Dispatches the structure to the correct dump routine. - * - ******************************************************************************/ - -void acpi_rs_dump_resource_list(struct acpi_resource *resource_list) -{ - u32 count = 0; - u32 type; - - ACPI_FUNCTION_ENTRY(); - - if (!(acpi_dbg_level & ACPI_LV_RESOURCES) - || !(_COMPONENT & acpi_dbg_layer)) { - return; - } - - /* Walk list and dump all resource descriptors (END_TAG terminates) */ - - do { - acpi_os_printf("\n[%02X] ", count); - count++; - - /* Validate Type before dispatch */ - - type = resource_list->type; - if (type > ACPI_RESOURCE_TYPE_MAX) { - acpi_os_printf - ("Invalid descriptor type (%X) in resource list\n", - resource_list->type); - return; - } - - /* Dump the resource descriptor */ - - acpi_rs_dump_descriptor(&resource_list->data, - acpi_gbl_dump_resource_dispatch[type]); - - /* Point to the next resource structure */ - - resource_list = - ACPI_ADD_PTR(struct acpi_resource, resource_list, - resource_list->length); - - /* Exit when END_TAG descriptor is reached */ - - } while (type != ACPI_RESOURCE_TYPE_END_TAG); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_irq_list - * - * PARAMETERS: route_table - Pointer to the routing table to dump. - * - * RETURN: None - * - * DESCRIPTION: Print IRQ routing table - * - ******************************************************************************/ - -void acpi_rs_dump_irq_list(u8 * route_table) -{ - struct acpi_pci_routing_table *prt_element; - u8 count; - - ACPI_FUNCTION_ENTRY(); - - if (!(acpi_dbg_level & ACPI_LV_RESOURCES) - || !(_COMPONENT & acpi_dbg_layer)) { - return; - } - - prt_element = ACPI_CAST_PTR(struct acpi_pci_routing_table, route_table); - - /* Dump all table elements, Exit on zero length element */ - - for (count = 0; prt_element->length; count++) { - acpi_os_printf("\n[%02X] PCI IRQ Routing Table Package\n", - count); - acpi_rs_dump_descriptor(prt_element, acpi_rs_dump_prt); - - prt_element = ACPI_ADD_PTR(struct acpi_pci_routing_table, - prt_element, prt_element->length); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_out* - * - * PARAMETERS: Title - Name of the resource field - * Value - Value of the resource field - * - * RETURN: None - * - * DESCRIPTION: Miscellaneous helper functions to consistently format the - * output of the resource dump routines - * - ******************************************************************************/ - -static void acpi_rs_out_string(char *title, char *value) -{ - acpi_os_printf("%27s : %s", title, value); - if (!*value) { - acpi_os_printf("[NULL NAMESTRING]"); - } - acpi_os_printf("\n"); -} - -static void acpi_rs_out_integer8(char *title, u8 value) -{ - acpi_os_printf("%27s : %2.2X\n", title, value); -} - -static void acpi_rs_out_integer16(char *title, u16 value) -{ - acpi_os_printf("%27s : %4.4X\n", title, value); -} - -static void acpi_rs_out_integer32(char *title, u32 value) -{ - acpi_os_printf("%27s : %8.8X\n", title, value); -} - -static void acpi_rs_out_integer64(char *title, u64 value) -{ - acpi_os_printf("%27s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value)); -} - -static void acpi_rs_out_title(char *title) -{ - acpi_os_printf("%27s : ", title); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump*List - * - * PARAMETERS: Length - Number of elements in the list - * Data - Start of the list - * - * RETURN: None - * - * DESCRIPTION: Miscellaneous functions to dump lists of raw data - * - ******************************************************************************/ - -static void acpi_rs_dump_byte_list(u16 length, u8 * data) -{ - u8 i; - - for (i = 0; i < length; i++) { - acpi_os_printf("%25s%2.2X : %2.2X\n", "Byte", i, data[i]); - } -} - -static void acpi_rs_dump_short_byte_list(u8 length, u8 * data) -{ - u8 i; - - for (i = 0; i < length; i++) { - acpi_os_printf("%X ", data[i]); - } - acpi_os_printf("\n"); -} - -static void acpi_rs_dump_dword_list(u8 length, u32 * data) -{ - u8 i; - - for (i = 0; i < length; i++) { - acpi_os_printf("%25s%2.2X : %8.8X\n", "Dword", i, data[i]); - } -} - -#endif diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c deleted file mode 100644 index aac41cc21344..000000000000 --- a/drivers/acpi/resources/rsinfo.c +++ /dev/null @@ -1,206 +0,0 @@ -/******************************************************************************* - * - * Module Name: rsinfo - Dispatch and Info tables - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rsinfo") - -/* - * Resource dispatch and information tables. Any new resource types (either - * Large or Small) must be reflected in each of these tables, so they are here - * in one place. - * - * The tables for Large descriptors are indexed by bits 6:0 of the AML - * descriptor type byte. The tables for Small descriptors are indexed by - * bits 6:3 of the descriptor byte. The tables for internal resource - * descriptors are indexed by the acpi_resource_type field. - */ -/* Dispatch table for resource-to-AML (Set Resource) conversion functions */ -struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[] = { - acpi_rs_set_irq, /* 0x00, ACPI_RESOURCE_TYPE_IRQ */ - acpi_rs_convert_dma, /* 0x01, ACPI_RESOURCE_TYPE_DMA */ - acpi_rs_set_start_dpf, /* 0x02, ACPI_RESOURCE_TYPE_START_DEPENDENT */ - acpi_rs_convert_end_dpf, /* 0x03, ACPI_RESOURCE_TYPE_END_DEPENDENT */ - acpi_rs_convert_io, /* 0x04, ACPI_RESOURCE_TYPE_IO */ - acpi_rs_convert_fixed_io, /* 0x05, ACPI_RESOURCE_TYPE_FIXED_IO */ - acpi_rs_set_vendor, /* 0x06, ACPI_RESOURCE_TYPE_VENDOR */ - acpi_rs_convert_end_tag, /* 0x07, ACPI_RESOURCE_TYPE_END_TAG */ - acpi_rs_convert_memory24, /* 0x08, ACPI_RESOURCE_TYPE_MEMORY24 */ - acpi_rs_convert_memory32, /* 0x09, ACPI_RESOURCE_TYPE_MEMORY32 */ - acpi_rs_convert_fixed_memory32, /* 0x0A, ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ - acpi_rs_convert_address16, /* 0x0B, ACPI_RESOURCE_TYPE_ADDRESS16 */ - acpi_rs_convert_address32, /* 0x0C, ACPI_RESOURCE_TYPE_ADDRESS32 */ - acpi_rs_convert_address64, /* 0x0D, ACPI_RESOURCE_TYPE_ADDRESS64 */ - acpi_rs_convert_ext_address64, /* 0x0E, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ - acpi_rs_convert_ext_irq, /* 0x0F, ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ - acpi_rs_convert_generic_reg /* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ -}; - -/* Dispatch tables for AML-to-resource (Get Resource) conversion functions */ - -struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[] = { - /* Small descriptors */ - - NULL, /* 0x00, Reserved */ - NULL, /* 0x01, Reserved */ - NULL, /* 0x02, Reserved */ - NULL, /* 0x03, Reserved */ - acpi_rs_get_irq, /* 0x04, ACPI_RESOURCE_NAME_IRQ */ - acpi_rs_convert_dma, /* 0x05, ACPI_RESOURCE_NAME_DMA */ - acpi_rs_get_start_dpf, /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */ - acpi_rs_convert_end_dpf, /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */ - acpi_rs_convert_io, /* 0x08, ACPI_RESOURCE_NAME_IO */ - acpi_rs_convert_fixed_io, /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO */ - NULL, /* 0x0A, Reserved */ - NULL, /* 0x0B, Reserved */ - NULL, /* 0x0C, Reserved */ - NULL, /* 0x0D, Reserved */ - acpi_rs_get_vendor_small, /* 0x0E, ACPI_RESOURCE_NAME_VENDOR_SMALL */ - acpi_rs_convert_end_tag, /* 0x0F, ACPI_RESOURCE_NAME_END_TAG */ - - /* Large descriptors */ - - NULL, /* 0x00, Reserved */ - acpi_rs_convert_memory24, /* 0x01, ACPI_RESOURCE_NAME_MEMORY24 */ - acpi_rs_convert_generic_reg, /* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */ - NULL, /* 0x03, Reserved */ - acpi_rs_get_vendor_large, /* 0x04, ACPI_RESOURCE_NAME_VENDOR_LARGE */ - acpi_rs_convert_memory32, /* 0x05, ACPI_RESOURCE_NAME_MEMORY32 */ - acpi_rs_convert_fixed_memory32, /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY32 */ - acpi_rs_convert_address32, /* 0x07, ACPI_RESOURCE_NAME_ADDRESS32 */ - acpi_rs_convert_address16, /* 0x08, ACPI_RESOURCE_NAME_ADDRESS16 */ - acpi_rs_convert_ext_irq, /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_IRQ */ - acpi_rs_convert_address64, /* 0x0A, ACPI_RESOURCE_NAME_ADDRESS64 */ - acpi_rs_convert_ext_address64 /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */ -}; - -#ifdef ACPI_FUTURE_USAGE -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) - -/* Dispatch table for resource dump functions */ - -struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = { - acpi_rs_dump_irq, /* ACPI_RESOURCE_TYPE_IRQ */ - acpi_rs_dump_dma, /* ACPI_RESOURCE_TYPE_DMA */ - acpi_rs_dump_start_dpf, /* ACPI_RESOURCE_TYPE_START_DEPENDENT */ - acpi_rs_dump_end_dpf, /* ACPI_RESOURCE_TYPE_END_DEPENDENT */ - acpi_rs_dump_io, /* ACPI_RESOURCE_TYPE_IO */ - acpi_rs_dump_fixed_io, /* ACPI_RESOURCE_TYPE_FIXED_IO */ - acpi_rs_dump_vendor, /* ACPI_RESOURCE_TYPE_VENDOR */ - acpi_rs_dump_end_tag, /* ACPI_RESOURCE_TYPE_END_TAG */ - acpi_rs_dump_memory24, /* ACPI_RESOURCE_TYPE_MEMORY24 */ - acpi_rs_dump_memory32, /* ACPI_RESOURCE_TYPE_MEMORY32 */ - acpi_rs_dump_fixed_memory32, /* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ - acpi_rs_dump_address16, /* ACPI_RESOURCE_TYPE_ADDRESS16 */ - acpi_rs_dump_address32, /* ACPI_RESOURCE_TYPE_ADDRESS32 */ - acpi_rs_dump_address64, /* ACPI_RESOURCE_TYPE_ADDRESS64 */ - acpi_rs_dump_ext_address64, /* ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ - acpi_rs_dump_ext_irq, /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ - acpi_rs_dump_generic_reg, /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ -}; -#endif - -#endif /* ACPI_FUTURE_USAGE */ -/* - * Base sizes for external AML resource descriptors, indexed by internal type. - * Includes size of the descriptor header (1 byte for small descriptors, - * 3 bytes for large descriptors) - */ -const u8 acpi_gbl_aml_resource_sizes[] = { - sizeof(struct aml_resource_irq), /* ACPI_RESOURCE_TYPE_IRQ (optional Byte 3 always created) */ - sizeof(struct aml_resource_dma), /* ACPI_RESOURCE_TYPE_DMA */ - sizeof(struct aml_resource_start_dependent), /* ACPI_RESOURCE_TYPE_START_DEPENDENT (optional Byte 1 always created) */ - sizeof(struct aml_resource_end_dependent), /* ACPI_RESOURCE_TYPE_END_DEPENDENT */ - sizeof(struct aml_resource_io), /* ACPI_RESOURCE_TYPE_IO */ - sizeof(struct aml_resource_fixed_io), /* ACPI_RESOURCE_TYPE_FIXED_IO */ - sizeof(struct aml_resource_vendor_small), /* ACPI_RESOURCE_TYPE_VENDOR */ - sizeof(struct aml_resource_end_tag), /* ACPI_RESOURCE_TYPE_END_TAG */ - sizeof(struct aml_resource_memory24), /* ACPI_RESOURCE_TYPE_MEMORY24 */ - sizeof(struct aml_resource_memory32), /* ACPI_RESOURCE_TYPE_MEMORY32 */ - sizeof(struct aml_resource_fixed_memory32), /* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ - sizeof(struct aml_resource_address16), /* ACPI_RESOURCE_TYPE_ADDRESS16 */ - sizeof(struct aml_resource_address32), /* ACPI_RESOURCE_TYPE_ADDRESS32 */ - sizeof(struct aml_resource_address64), /* ACPI_RESOURCE_TYPE_ADDRESS64 */ - sizeof(struct aml_resource_extended_address64), /*ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ - sizeof(struct aml_resource_extended_irq), /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ - sizeof(struct aml_resource_generic_register) /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ -}; - -const u8 acpi_gbl_resource_struct_sizes[] = { - /* Small descriptors */ - - 0, - 0, - 0, - 0, - ACPI_RS_SIZE(struct acpi_resource_irq), - ACPI_RS_SIZE(struct acpi_resource_dma), - ACPI_RS_SIZE(struct acpi_resource_start_dependent), - ACPI_RS_SIZE_MIN, - ACPI_RS_SIZE(struct acpi_resource_io), - ACPI_RS_SIZE(struct acpi_resource_fixed_io), - 0, - 0, - 0, - 0, - ACPI_RS_SIZE(struct acpi_resource_vendor), - ACPI_RS_SIZE_MIN, - - /* Large descriptors */ - - 0, - ACPI_RS_SIZE(struct acpi_resource_memory24), - ACPI_RS_SIZE(struct acpi_resource_generic_register), - 0, - ACPI_RS_SIZE(struct acpi_resource_vendor), - ACPI_RS_SIZE(struct acpi_resource_memory32), - ACPI_RS_SIZE(struct acpi_resource_fixed_memory32), - ACPI_RS_SIZE(struct acpi_resource_address32), - ACPI_RS_SIZE(struct acpi_resource_address16), - ACPI_RS_SIZE(struct acpi_resource_extended_irq), - ACPI_RS_SIZE(struct acpi_resource_address64), - ACPI_RS_SIZE(struct acpi_resource_extended_address64) -}; diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c deleted file mode 100644 index d31129aca400..000000000000 --- a/drivers/acpi/resources/rsio.c +++ /dev/null @@ -1,290 +0,0 @@ -/******************************************************************************* - * - * Module Name: rsio - IO and DMA resource descriptors - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rsio") - -/******************************************************************************* - * - * acpi_rs_convert_io - * - ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_convert_io[5] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IO, - ACPI_RS_SIZE(struct acpi_resource_io), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IO, - sizeof(struct aml_resource_io), - 0}, - - /* Decode flag */ - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.io.io_decode), - AML_OFFSET(io.flags), - 0}, - /* - * These fields are contiguous in both the source and destination: - * Address Alignment - * Length - * Minimum Base Address - * Maximum Base Address - */ - {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.io.alignment), - AML_OFFSET(io.alignment), - 2}, - - {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.io.minimum), - AML_OFFSET(io.minimum), - 2} -}; - -/******************************************************************************* - * - * acpi_rs_convert_fixed_io - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_convert_fixed_io[4] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_IO, - ACPI_RS_SIZE(struct acpi_resource_fixed_io), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_io)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_IO, - sizeof(struct aml_resource_fixed_io), - 0}, - /* - * These fields are contiguous in both the source and destination: - * Base Address - * Length - */ - {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.fixed_io.address_length), - AML_OFFSET(fixed_io.address_length), - 1}, - - {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.fixed_io.address), - AML_OFFSET(fixed_io.address), - 1} -}; - -/******************************************************************************* - * - * acpi_rs_convert_generic_reg - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_convert_generic_reg[4] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GENERIC_REGISTER, - ACPI_RS_SIZE(struct acpi_resource_generic_register), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_generic_reg)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_GENERIC_REGISTER, - sizeof(struct aml_resource_generic_register), - 0}, - /* - * These fields are contiguous in both the source and destination: - * Address Space ID - * Register Bit Width - * Register Bit Offset - * Access Size - */ - {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.generic_reg.space_id), - AML_OFFSET(generic_reg.address_space_id), - 4}, - - /* Get the Register Address */ - - {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.generic_reg.address), - AML_OFFSET(generic_reg.address), - 1} -}; - -/******************************************************************************* - * - * acpi_rs_convert_end_dpf - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_convert_end_dpf[2] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_DEPENDENT, - ACPI_RS_SIZE_MIN, - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_end_dpf)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_DEPENDENT, - sizeof(struct aml_resource_end_dependent), - 0} -}; - -/******************************************************************************* - * - * acpi_rs_convert_end_tag - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_convert_end_tag[2] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_TAG, - ACPI_RS_SIZE_MIN, - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_end_tag)}, - - /* - * Note: The checksum field is set to zero, meaning that the resource - * data is treated as if the checksum operation succeeded. - * (ACPI Spec 1.0b Section 6.4.2.8) - */ - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_TAG, - sizeof(struct aml_resource_end_tag), - 0} -}; - -/******************************************************************************* - * - * acpi_rs_get_start_dpf - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_get_start_dpf[6] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_START_DEPENDENT, - ACPI_RS_SIZE(struct acpi_resource_start_dependent), - ACPI_RSC_TABLE_SIZE(acpi_rs_get_start_dpf)}, - - /* Defaults for Compatibility and Performance priorities */ - - {ACPI_RSC_SET8, ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), - ACPI_ACCEPTABLE_CONFIGURATION, - 2}, - - /* Get the descriptor length (0 or 1 for Start Dpf descriptor) */ - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.start_dpf.descriptor_length), - AML_OFFSET(start_dpf.descriptor_type), - 0}, - - /* All done if there is no flag byte present in the descriptor */ - - {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 1}, - - /* Flag byte is present, get the flags */ - - {ACPI_RSC_2BITFLAG, - ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), - AML_OFFSET(start_dpf.flags), - 0}, - - {ACPI_RSC_2BITFLAG, - ACPI_RS_OFFSET(data.start_dpf.performance_robustness), - AML_OFFSET(start_dpf.flags), - 2} -}; - -/******************************************************************************* - * - * acpi_rs_set_start_dpf - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_set_start_dpf[10] = { - /* Start with a default descriptor of length 1 */ - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_START_DEPENDENT, - sizeof(struct aml_resource_start_dependent), - ACPI_RSC_TABLE_SIZE(acpi_rs_set_start_dpf)}, - - /* Set the default flag values */ - - {ACPI_RSC_2BITFLAG, - ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), - AML_OFFSET(start_dpf.flags), - 0}, - - {ACPI_RSC_2BITFLAG, - ACPI_RS_OFFSET(data.start_dpf.performance_robustness), - AML_OFFSET(start_dpf.flags), - 2}, - /* - * All done if the output descriptor length is required to be 1 - * (i.e., optimization to 0 bytes cannot be attempted) - */ - {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, - ACPI_RS_OFFSET(data.start_dpf.descriptor_length), - 1}, - - /* Set length to 0 bytes (no flags byte) */ - - {ACPI_RSC_LENGTH, 0, 0, - sizeof(struct aml_resource_start_dependent_noprio)}, - - /* - * All done if the output descriptor length is required to be 0. - * - * TBD: Perhaps we should check for error if input flags are not - * compatible with a 0-byte descriptor. - */ - {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, - ACPI_RS_OFFSET(data.start_dpf.descriptor_length), - 0}, - - /* Reset length to 1 byte (descriptor with flags byte) */ - - {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_start_dependent)}, - - /* - * All done if flags byte is necessary -- if either priority value - * is not ACPI_ACCEPTABLE_CONFIGURATION - */ - {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, - ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), - ACPI_ACCEPTABLE_CONFIGURATION}, - - {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, - ACPI_RS_OFFSET(data.start_dpf.performance_robustness), - ACPI_ACCEPTABLE_CONFIGURATION}, - - /* Flag byte is not necessary */ - - {ACPI_RSC_LENGTH, 0, 0, - sizeof(struct aml_resource_start_dependent_noprio)} -}; diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c deleted file mode 100644 index 9a5a08d67313..000000000000 --- a/drivers/acpi/resources/rsirq.c +++ /dev/null @@ -1,266 +0,0 @@ -/******************************************************************************* - * - * Module Name: rsirq - IRQ resource descriptors - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rsirq") - -/******************************************************************************* - * - * acpi_rs_get_irq - * - ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_get_irq[8] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, - ACPI_RS_SIZE(struct acpi_resource_irq), - ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)}, - - /* Get the IRQ mask (bytes 1:2) */ - - {ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]), - AML_OFFSET(irq.irq_mask), - ACPI_RS_OFFSET(data.irq.interrupt_count)}, - - /* Set default flags (others are zero) */ - - {ACPI_RSC_SET8, ACPI_RS_OFFSET(data.irq.triggering), - ACPI_EDGE_SENSITIVE, - 1}, - - /* Get the descriptor length (2 or 3 for IRQ descriptor) */ - - {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.irq.descriptor_length), - AML_OFFSET(irq.descriptor_type), - 0}, - - /* All done if no flag byte present in descriptor */ - - {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, - - /* Get flags: Triggering[0], Polarity[3], Sharing[4] */ - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), - AML_OFFSET(irq.flags), - 0}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity), - AML_OFFSET(irq.flags), - 3}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), - AML_OFFSET(irq.flags), - 4} -}; - -/******************************************************************************* - * - * acpi_rs_set_irq - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_set_irq[13] = { - /* Start with a default descriptor of length 3 */ - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, - sizeof(struct aml_resource_irq), - ACPI_RSC_TABLE_SIZE(acpi_rs_set_irq)}, - - /* Convert interrupt list to 16-bit IRQ bitmask */ - - {ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]), - AML_OFFSET(irq.irq_mask), - ACPI_RS_OFFSET(data.irq.interrupt_count)}, - - /* Set the flags byte */ - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), - AML_OFFSET(irq.flags), - 0}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity), - AML_OFFSET(irq.flags), - 3}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), - AML_OFFSET(irq.flags), - 4}, - - /* - * All done if the output descriptor length is required to be 3 - * (i.e., optimization to 2 bytes cannot be attempted) - */ - {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, - ACPI_RS_OFFSET(data.irq.descriptor_length), - 3}, - - /* Set length to 2 bytes (no flags byte) */ - - {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)}, - - /* - * All done if the output descriptor length is required to be 2. - * - * TBD: Perhaps we should check for error if input flags are not - * compatible with a 2-byte descriptor. - */ - {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, - ACPI_RS_OFFSET(data.irq.descriptor_length), - 2}, - - /* Reset length to 3 bytes (descriptor with flags byte) */ - - {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq)}, - - /* - * Check if the flags byte is necessary. Not needed if the flags are: - * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE - */ - {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, - ACPI_RS_OFFSET(data.irq.triggering), - ACPI_EDGE_SENSITIVE}, - - {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, - ACPI_RS_OFFSET(data.irq.polarity), - ACPI_ACTIVE_HIGH}, - - {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, - ACPI_RS_OFFSET(data.irq.sharable), - ACPI_EXCLUSIVE}, - - /* We can optimize to a 2-byte irq_no_flags() descriptor */ - - {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)} -}; - -/******************************************************************************* - * - * acpi_rs_convert_ext_irq - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ, - ACPI_RS_SIZE(struct acpi_resource_extended_irq), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_irq)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_IRQ, - sizeof(struct aml_resource_extended_irq), - 0}, - - /* Flag bits */ - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.producer_consumer), - AML_OFFSET(extended_irq.flags), - 0}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.triggering), - AML_OFFSET(extended_irq.flags), - 1}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.polarity), - AML_OFFSET(extended_irq.flags), - 2}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.sharable), - AML_OFFSET(extended_irq.flags), - 3}, - - /* IRQ Table length (Byte4) */ - - {ACPI_RSC_COUNT, ACPI_RS_OFFSET(data.extended_irq.interrupt_count), - AML_OFFSET(extended_irq.interrupt_count), - sizeof(u32)} - , - - /* Copy every IRQ in the table, each is 32 bits */ - - {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.extended_irq.interrupts[0]), - AML_OFFSET(extended_irq.interrupts[0]), - 0} - , - - /* Optional resource_source (Index and String) */ - - {ACPI_RSC_SOURCEX, ACPI_RS_OFFSET(data.extended_irq.resource_source), - ACPI_RS_OFFSET(data.extended_irq.interrupts[0]), - sizeof(struct aml_resource_extended_irq)} -}; - -/******************************************************************************* - * - * acpi_rs_convert_dma - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_convert_dma[6] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_DMA, - ACPI_RS_SIZE(struct acpi_resource_dma), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_dma)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_DMA, - sizeof(struct aml_resource_dma), - 0}, - - /* Flags: transfer preference, bus mastering, channel speed */ - - {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.transfer), - AML_OFFSET(dma.flags), - 0}, - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.dma.bus_master), - AML_OFFSET(dma.flags), - 2}, - - {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.type), - AML_OFFSET(dma.flags), - 5}, - - /* DMA channel mask bits */ - - {ACPI_RSC_BITMASK, ACPI_RS_OFFSET(data.dma.channels[0]), - AML_OFFSET(dma.dma_channel_mask), - ACPI_RS_OFFSET(data.dma.channel_count)} -}; diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c deleted file mode 100644 index 483389871a50..000000000000 --- a/drivers/acpi/resources/rslist.c +++ /dev/null @@ -1,203 +0,0 @@ -/******************************************************************************* - * - * Module Name: rslist - Linked list utilities - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rslist") - -/******************************************************************************* - * - * FUNCTION: acpi_rs_convert_aml_to_resources - * - * PARAMETERS: acpi_walk_aml_callback - * resource_ptr - Pointer to the buffer that will - * contain the output structures - * - * RETURN: Status - * - * DESCRIPTION: Convert an AML resource to an internal representation of the - * resource that is aligned and easier to access. - * - ******************************************************************************/ -acpi_status -acpi_rs_convert_aml_to_resources(u8 * aml, - u32 length, - u32 offset, u8 resource_index, void **context) -{ - struct acpi_resource **resource_ptr = - ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context); - struct acpi_resource *resource; - acpi_status status; - - ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources); - - /* - * Check that the input buffer and all subsequent pointers into it - * are aligned on a native word boundary. Most important on IA64 - */ - resource = *resource_ptr; - if (ACPI_IS_MISALIGNED(resource)) { - ACPI_WARNING((AE_INFO, - "Misaligned resource pointer %p", resource)); - } - - /* Convert the AML byte stream resource to a local resource struct */ - - status = - acpi_rs_convert_aml_to_resource(resource, - ACPI_CAST_PTR(union aml_resource, - aml), - acpi_gbl_get_resource_dispatch - [resource_index]); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not convert AML resource (Type %X)", - *aml)); - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Type %.2X, AmlLength %.2X InternalLength %.2X\n", - acpi_ut_get_resource_type(aml), length, - resource->length)); - - /* Point to the next structure in the output buffer */ - - *resource_ptr = ACPI_ADD_PTR(void, resource, resource->length); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_convert_resources_to_aml - * - * PARAMETERS: Resource - Pointer to the resource linked list - * aml_size_needed - Calculated size of the byte stream - * needed from calling acpi_rs_get_aml_length() - * The size of the output_buffer is - * guaranteed to be >= aml_size_needed - * output_buffer - Pointer to the buffer that will - * contain the byte stream - * - * RETURN: Status - * - * DESCRIPTION: Takes the resource linked list and parses it, creating a - * byte stream of resources in the caller's output buffer - * - ******************************************************************************/ - -acpi_status -acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, - acpi_size aml_size_needed, u8 * output_buffer) -{ - u8 *aml = output_buffer; - u8 *end_aml = output_buffer + aml_size_needed; - acpi_status status; - - ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml); - - /* Walk the resource descriptor list, convert each descriptor */ - - while (aml < end_aml) { - - /* Validate the (internal) Resource Type */ - - if (resource->type > ACPI_RESOURCE_TYPE_MAX) { - ACPI_ERROR((AE_INFO, - "Invalid descriptor type (%X) in resource list", - resource->type)); - return_ACPI_STATUS(AE_BAD_DATA); - } - - /* Perform the conversion */ - - status = acpi_rs_convert_resource_to_aml(resource, ACPI_CAST_PTR(union - aml_resource, - aml), - acpi_gbl_set_resource_dispatch - [resource->type]); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not convert resource (type %X) to AML", - resource->type)); - return_ACPI_STATUS(status); - } - - /* Perform final sanity check on the new AML resource descriptor */ - - status = - acpi_ut_validate_resource(ACPI_CAST_PTR - (union aml_resource, aml), NULL); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Check for end-of-list, normal exit */ - - if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { - - /* An End Tag indicates the end of the input Resource Template */ - - return_ACPI_STATUS(AE_OK); - } - - /* - * Extract the total length of the new descriptor and set the - * Aml to point to the next (output) resource descriptor - */ - aml += acpi_ut_get_descriptor_length(aml); - - /* Point to the next input resource descriptor */ - - resource = - ACPI_ADD_PTR(struct acpi_resource, resource, - resource->length); - } - - /* Completed buffer, but did not find an end_tag resource descriptor */ - - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); -} diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c deleted file mode 100644 index 5fd3746cca54..000000000000 --- a/drivers/acpi/resources/rsmemory.c +++ /dev/null @@ -1,236 +0,0 @@ -/******************************************************************************* - * - * Module Name: rsmem24 - Memory resource descriptors - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rsmemory") - -/******************************************************************************* - * - * acpi_rs_convert_memory24 - * - ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_convert_memory24[4] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY24, - ACPI_RS_SIZE(struct acpi_resource_memory24), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_memory24)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY24, - sizeof(struct aml_resource_memory24), - 0}, - - /* Read/Write bit */ - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.memory24.write_protect), - AML_OFFSET(memory24.flags), - 0}, - /* - * These fields are contiguous in both the source and destination: - * Minimum Base Address - * Maximum Base Address - * Address Base Alignment - * Range Length - */ - {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.memory24.minimum), - AML_OFFSET(memory24.minimum), - 4} -}; - -/******************************************************************************* - * - * acpi_rs_convert_memory32 - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_convert_memory32[4] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY32, - ACPI_RS_SIZE(struct acpi_resource_memory32), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_memory32)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY32, - sizeof(struct aml_resource_memory32), - 0}, - - /* Read/Write bit */ - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.memory32.write_protect), - AML_OFFSET(memory32.flags), - 0}, - /* - * These fields are contiguous in both the source and destination: - * Minimum Base Address - * Maximum Base Address - * Address Base Alignment - * Range Length - */ - {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.memory32.minimum), - AML_OFFSET(memory32.minimum), - 4} -}; - -/******************************************************************************* - * - * acpi_rs_convert_fixed_memory32 - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_convert_fixed_memory32[4] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_MEMORY32, - ACPI_RS_SIZE(struct acpi_resource_fixed_memory32), - ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_memory32)}, - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_MEMORY32, - sizeof(struct aml_resource_fixed_memory32), - 0}, - - /* Read/Write bit */ - - {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.fixed_memory32.write_protect), - AML_OFFSET(fixed_memory32.flags), - 0}, - /* - * These fields are contiguous in both the source and destination: - * Base Address - * Range Length - */ - {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.fixed_memory32.address), - AML_OFFSET(fixed_memory32.address), - 2} -}; - -/******************************************************************************* - * - * acpi_rs_get_vendor_small - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_get_vendor_small[3] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR, - ACPI_RS_SIZE(struct acpi_resource_vendor), - ACPI_RSC_TABLE_SIZE(acpi_rs_get_vendor_small)}, - - /* Length of the vendor data (byte count) */ - - {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), - 0, - sizeof(u8)} - , - - /* Vendor data */ - - {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), - sizeof(struct aml_resource_small_header), - 0} -}; - -/******************************************************************************* - * - * acpi_rs_get_vendor_large - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_get_vendor_large[3] = { - {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR, - ACPI_RS_SIZE(struct acpi_resource_vendor), - ACPI_RSC_TABLE_SIZE(acpi_rs_get_vendor_large)}, - - /* Length of the vendor data (byte count) */ - - {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), - 0, - sizeof(u8)} - , - - /* Vendor data */ - - {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), - sizeof(struct aml_resource_large_header), - 0} -}; - -/******************************************************************************* - * - * acpi_rs_set_vendor - * - ******************************************************************************/ - -struct acpi_rsconvert_info acpi_rs_set_vendor[7] = { - /* Default is a small vendor descriptor */ - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_SMALL, - sizeof(struct aml_resource_small_header), - ACPI_RSC_TABLE_SIZE(acpi_rs_set_vendor)}, - - /* Get the length and copy the data */ - - {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), - 0, - 0}, - - {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), - sizeof(struct aml_resource_small_header), - 0}, - - /* - * All done if the Vendor byte length is 7 or less, meaning that it will - * fit within a small descriptor - */ - {ACPI_RSC_EXIT_LE, 0, 0, 7}, - - /* Must create a large vendor descriptor */ - - {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_LARGE, - sizeof(struct aml_resource_large_header), - 0}, - - {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), - 0, - 0}, - - {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), - sizeof(struct aml_resource_large_header), - 0} -}; diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c deleted file mode 100644 index 2cd6e8cfaba1..000000000000 --- a/drivers/acpi/resources/rsmisc.c +++ /dev/null @@ -1,561 +0,0 @@ -/******************************************************************************* - * - * Module Name: rsmisc - Miscellaneous resource descriptors - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rsmisc") -#define INIT_RESOURCE_TYPE(i) i->resource_offset -#define INIT_RESOURCE_LENGTH(i) i->aml_offset -#define INIT_TABLE_LENGTH(i) i->value -#define COMPARE_OPCODE(i) i->resource_offset -#define COMPARE_TARGET(i) i->aml_offset -#define COMPARE_VALUE(i) i->value -/******************************************************************************* - * - * FUNCTION: acpi_rs_convert_aml_to_resource - * - * PARAMETERS: Resource - Pointer to the resource descriptor - * Aml - Where the AML descriptor is returned - * Info - Pointer to appropriate conversion table - * - * RETURN: Status - * - * DESCRIPTION: Convert an external AML resource descriptor to the corresponding - * internal resource descriptor - * - ******************************************************************************/ -acpi_status -acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, - union aml_resource *aml, - struct acpi_rsconvert_info *info) -{ - acpi_rs_length aml_resource_length; - void *source; - void *destination; - char *target; - u8 count; - u8 flags_mode = FALSE; - u16 item_count = 0; - u16 temp16 = 0; - - ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource); - - if (((acpi_size) resource) & 0x3) { - - /* Each internal resource struct is expected to be 32-bit aligned */ - - ACPI_WARNING((AE_INFO, - "Misaligned resource pointer (get): %p Type %2.2X Len %X", - resource, resource->type, resource->length)); - } - - /* Extract the resource Length field (does not include header length) */ - - aml_resource_length = acpi_ut_get_resource_length(aml); - - /* - * First table entry must be ACPI_RSC_INITxxx and must contain the - * table length (# of table entries) - */ - count = INIT_TABLE_LENGTH(info); - - while (count) { - /* - * Source is the external AML byte stream buffer, - * destination is the internal resource descriptor - */ - source = ACPI_ADD_PTR(void, aml, info->aml_offset); - destination = - ACPI_ADD_PTR(void, resource, info->resource_offset); - - switch (info->opcode) { - case ACPI_RSC_INITGET: - /* - * Get the resource type and the initial (minimum) length - */ - ACPI_MEMSET(resource, 0, INIT_RESOURCE_LENGTH(info)); - resource->type = INIT_RESOURCE_TYPE(info); - resource->length = INIT_RESOURCE_LENGTH(info); - break; - - case ACPI_RSC_INITSET: - break; - - case ACPI_RSC_FLAGINIT: - - flags_mode = TRUE; - break; - - case ACPI_RSC_1BITFLAG: - /* - * Mask and shift the flag bit - */ - ACPI_SET8(destination) = (u8) - ((ACPI_GET8(source) >> info->value) & 0x01); - break; - - case ACPI_RSC_2BITFLAG: - /* - * Mask and shift the flag bits - */ - ACPI_SET8(destination) = (u8) - ((ACPI_GET8(source) >> info->value) & 0x03); - break; - - case ACPI_RSC_COUNT: - - item_count = ACPI_GET8(source); - ACPI_SET8(destination) = (u8) item_count; - - resource->length = resource->length + - (info->value * (item_count - 1)); - break; - - case ACPI_RSC_COUNT16: - - item_count = aml_resource_length; - ACPI_SET16(destination) = item_count; - - resource->length = resource->length + - (info->value * (item_count - 1)); - break; - - case ACPI_RSC_LENGTH: - - resource->length = resource->length + info->value; - break; - - case ACPI_RSC_MOVE8: - case ACPI_RSC_MOVE16: - case ACPI_RSC_MOVE32: - case ACPI_RSC_MOVE64: - /* - * Raw data move. Use the Info value field unless item_count has - * been previously initialized via a COUNT opcode - */ - if (info->value) { - item_count = info->value; - } - acpi_rs_move_data(destination, source, item_count, - info->opcode); - break; - - case ACPI_RSC_SET8: - - ACPI_MEMSET(destination, info->aml_offset, info->value); - break; - - case ACPI_RSC_DATA8: - - target = ACPI_ADD_PTR(char, resource, info->value); - ACPI_MEMCPY(destination, source, ACPI_GET16(target)); - break; - - case ACPI_RSC_ADDRESS: - /* - * Common handler for address descriptor flags - */ - if (!acpi_rs_get_address_common(resource, aml)) { - return_ACPI_STATUS - (AE_AML_INVALID_RESOURCE_TYPE); - } - break; - - case ACPI_RSC_SOURCE: - /* - * Optional resource_source (Index and String) - */ - resource->length += - acpi_rs_get_resource_source(aml_resource_length, - info->value, - destination, aml, NULL); - break; - - case ACPI_RSC_SOURCEX: - /* - * Optional resource_source (Index and String). This is the more - * complicated case used by the Interrupt() macro - */ - target = - ACPI_ADD_PTR(char, resource, - info->aml_offset + (item_count * 4)); - - resource->length += - acpi_rs_get_resource_source(aml_resource_length, - (acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target); - break; - - case ACPI_RSC_BITMASK: - /* - * 8-bit encoded bitmask (DMA macro) - */ - item_count = - acpi_rs_decode_bitmask(ACPI_GET8(source), - destination); - if (item_count) { - resource->length += (item_count - 1); - } - - target = ACPI_ADD_PTR(char, resource, info->value); - ACPI_SET8(target) = (u8) item_count; - break; - - case ACPI_RSC_BITMASK16: - /* - * 16-bit encoded bitmask (IRQ macro) - */ - ACPI_MOVE_16_TO_16(&temp16, source); - - item_count = - acpi_rs_decode_bitmask(temp16, destination); - if (item_count) { - resource->length += (item_count - 1); - } - - target = ACPI_ADD_PTR(char, resource, info->value); - ACPI_SET8(target) = (u8) item_count; - break; - - case ACPI_RSC_EXIT_NE: - /* - * Control - Exit conversion if not equal - */ - switch (info->resource_offset) { - case ACPI_RSC_COMPARE_AML_LENGTH: - if (aml_resource_length != info->value) { - goto exit; - } - break; - - case ACPI_RSC_COMPARE_VALUE: - if (ACPI_GET8(source) != info->value) { - goto exit; - } - break; - - default: - - ACPI_ERROR((AE_INFO, - "Invalid conversion sub-opcode")); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - break; - - default: - - ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - count--; - info++; - } - - exit: - if (!flags_mode) { - - /* Round the resource struct length up to the next boundary (32 or 64) */ - - resource->length = - (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length); - } - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_convert_resource_to_aml - * - * PARAMETERS: Resource - Pointer to the resource descriptor - * Aml - Where the AML descriptor is returned - * Info - Pointer to appropriate conversion table - * - * RETURN: Status - * - * DESCRIPTION: Convert an internal resource descriptor to the corresponding - * external AML resource descriptor. - * - ******************************************************************************/ - -acpi_status -acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, - union aml_resource *aml, - struct acpi_rsconvert_info *info) -{ - void *source = NULL; - void *destination; - acpi_rsdesc_size aml_length = 0; - u8 count; - u16 temp16 = 0; - u16 item_count = 0; - - ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml); - - /* - * First table entry must be ACPI_RSC_INITxxx and must contain the - * table length (# of table entries) - */ - count = INIT_TABLE_LENGTH(info); - - while (count) { - /* - * Source is the internal resource descriptor, - * destination is the external AML byte stream buffer - */ - source = ACPI_ADD_PTR(void, resource, info->resource_offset); - destination = ACPI_ADD_PTR(void, aml, info->aml_offset); - - switch (info->opcode) { - case ACPI_RSC_INITSET: - - ACPI_MEMSET(aml, 0, INIT_RESOURCE_LENGTH(info)); - aml_length = INIT_RESOURCE_LENGTH(info); - acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info), - aml_length, aml); - break; - - case ACPI_RSC_INITGET: - break; - - case ACPI_RSC_FLAGINIT: - /* - * Clear the flag byte - */ - ACPI_SET8(destination) = 0; - break; - - case ACPI_RSC_1BITFLAG: - /* - * Mask and shift the flag bit - */ - ACPI_SET8(destination) |= (u8) - ((ACPI_GET8(source) & 0x01) << info->value); - break; - - case ACPI_RSC_2BITFLAG: - /* - * Mask and shift the flag bits - */ - ACPI_SET8(destination) |= (u8) - ((ACPI_GET8(source) & 0x03) << info->value); - break; - - case ACPI_RSC_COUNT: - - item_count = ACPI_GET8(source); - ACPI_SET8(destination) = (u8) item_count; - - aml_length = - (u16) (aml_length + - (info->value * (item_count - 1))); - break; - - case ACPI_RSC_COUNT16: - - item_count = ACPI_GET16(source); - aml_length = (u16) (aml_length + item_count); - acpi_rs_set_resource_length(aml_length, aml); - break; - - case ACPI_RSC_LENGTH: - - acpi_rs_set_resource_length(info->value, aml); - break; - - case ACPI_RSC_MOVE8: - case ACPI_RSC_MOVE16: - case ACPI_RSC_MOVE32: - case ACPI_RSC_MOVE64: - - if (info->value) { - item_count = info->value; - } - acpi_rs_move_data(destination, source, item_count, - info->opcode); - break; - - case ACPI_RSC_ADDRESS: - - /* Set the Resource Type, General Flags, and Type-Specific Flags */ - - acpi_rs_set_address_common(aml, resource); - break; - - case ACPI_RSC_SOURCEX: - /* - * Optional resource_source (Index and String) - */ - aml_length = - acpi_rs_set_resource_source(aml, (acpi_rs_length) - aml_length, source); - acpi_rs_set_resource_length(aml_length, aml); - break; - - case ACPI_RSC_SOURCE: - /* - * Optional resource_source (Index and String). This is the more - * complicated case used by the Interrupt() macro - */ - aml_length = - acpi_rs_set_resource_source(aml, info->value, - source); - acpi_rs_set_resource_length(aml_length, aml); - break; - - case ACPI_RSC_BITMASK: - /* - * 8-bit encoded bitmask (DMA macro) - */ - ACPI_SET8(destination) = (u8) - acpi_rs_encode_bitmask(source, - *ACPI_ADD_PTR(u8, resource, - info->value)); - break; - - case ACPI_RSC_BITMASK16: - /* - * 16-bit encoded bitmask (IRQ macro) - */ - temp16 = acpi_rs_encode_bitmask(source, - *ACPI_ADD_PTR(u8, - resource, - info-> - value)); - ACPI_MOVE_16_TO_16(destination, &temp16); - break; - - case ACPI_RSC_EXIT_LE: - /* - * Control - Exit conversion if less than or equal - */ - if (item_count <= info->value) { - goto exit; - } - break; - - case ACPI_RSC_EXIT_NE: - /* - * Control - Exit conversion if not equal - */ - switch (COMPARE_OPCODE(info)) { - case ACPI_RSC_COMPARE_VALUE: - - if (*ACPI_ADD_PTR(u8, resource, - COMPARE_TARGET(info)) != - COMPARE_VALUE(info)) { - goto exit; - } - break; - - default: - - ACPI_ERROR((AE_INFO, - "Invalid conversion sub-opcode")); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - break; - - case ACPI_RSC_EXIT_EQ: - /* - * Control - Exit conversion if equal - */ - if (*ACPI_ADD_PTR(u8, resource, - COMPARE_TARGET(info)) == - COMPARE_VALUE(info)) { - goto exit; - } - break; - - default: - - ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - count--; - info++; - } - - exit: - return_ACPI_STATUS(AE_OK); -} - -#if 0 -/* Previous resource validations */ - -if (aml->ext_address64.revision_iD != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) { - return_ACPI_STATUS(AE_SUPPORT); -} - -if (resource->data.start_dpf.performance_robustness >= 3) { - return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE); -} - -if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) { - /* - * Only [active_high, edge_sensitive] or [active_low, level_sensitive] - * polarity/trigger interrupts are allowed (ACPI spec, section - * "IRQ Format"), so 0x00 and 0x09 are illegal. - */ - ACPI_ERROR((AE_INFO, - "Invalid interrupt polarity/trigger in resource list, %X", - aml->irq.flags)); - return_ACPI_STATUS(AE_BAD_DATA); -} - -resource->data.extended_irq.interrupt_count = temp8; -if (temp8 < 1) { - - /* Must have at least one IRQ */ - - return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); -} - -if (resource->data.dma.transfer == 0x03) { - ACPI_ERROR((AE_INFO, "Invalid DMA.Transfer preference (3)")); - return_ACPI_STATUS(AE_BAD_DATA); -} -#endif diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c deleted file mode 100644 index 7450105f8548..000000000000 --- a/drivers/acpi/resources/rsutils.c +++ /dev/null @@ -1,727 +0,0 @@ -/******************************************************************************* - * - * Module Name: rsutils - Utilities for the resource manager - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rsutils") - -/******************************************************************************* - * - * FUNCTION: acpi_rs_decode_bitmask - * - * PARAMETERS: Mask - Bitmask to decode - * List - Where the converted list is returned - * - * RETURN: Count of bits set (length of list) - * - * DESCRIPTION: Convert a bit mask into a list of values - * - ******************************************************************************/ -u8 acpi_rs_decode_bitmask(u16 mask, u8 * list) -{ - u8 i; - u8 bit_count; - - ACPI_FUNCTION_ENTRY(); - - /* Decode the mask bits */ - - for (i = 0, bit_count = 0; mask; i++) { - if (mask & 0x0001) { - list[bit_count] = i; - bit_count++; - } - - mask >>= 1; - } - - return (bit_count); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_encode_bitmask - * - * PARAMETERS: List - List of values to encode - * Count - Length of list - * - * RETURN: Encoded bitmask - * - * DESCRIPTION: Convert a list of values to an encoded bitmask - * - ******************************************************************************/ - -u16 acpi_rs_encode_bitmask(u8 * list, u8 count) -{ - u32 i; - u16 mask; - - ACPI_FUNCTION_ENTRY(); - - /* Encode the list into a single bitmask */ - - for (i = 0, mask = 0; i < count; i++) { - mask |= (0x1 << list[i]); - } - - return mask; -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_move_data - * - * PARAMETERS: Destination - Pointer to the destination descriptor - * Source - Pointer to the source descriptor - * item_count - How many items to move - * move_type - Byte width - * - * RETURN: None - * - * DESCRIPTION: Move multiple data items from one descriptor to another. Handles - * alignment issues and endian issues if necessary, as configured - * via the ACPI_MOVE_* macros. (This is why a memcpy is not used) - * - ******************************************************************************/ - -void -acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) -{ - u32 i; - - ACPI_FUNCTION_ENTRY(); - - /* One move per item */ - - for (i = 0; i < item_count; i++) { - switch (move_type) { - /* - * For the 8-bit case, we can perform the move all at once - * since there are no alignment or endian issues - */ - case ACPI_RSC_MOVE8: - ACPI_MEMCPY(destination, source, item_count); - return; - - /* - * 16-, 32-, and 64-bit cases must use the move macros that perform - * endian conversion and/or accomodate hardware that cannot perform - * misaligned memory transfers - */ - case ACPI_RSC_MOVE16: - ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i], - &ACPI_CAST_PTR(u16, source)[i]); - break; - - case ACPI_RSC_MOVE32: - ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i], - &ACPI_CAST_PTR(u32, source)[i]); - break; - - case ACPI_RSC_MOVE64: - ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i], - &ACPI_CAST_PTR(u64, source)[i]); - break; - - default: - return; - } - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_set_resource_length - * - * PARAMETERS: total_length - Length of the AML descriptor, including - * the header and length fields. - * Aml - Pointer to the raw AML descriptor - * - * RETURN: None - * - * DESCRIPTION: Set the resource_length field of an AML - * resource descriptor, both Large and Small descriptors are - * supported automatically. Note: Descriptor Type field must - * be valid. - * - ******************************************************************************/ - -void -acpi_rs_set_resource_length(acpi_rsdesc_size total_length, - union aml_resource *aml) -{ - acpi_rs_length resource_length; - - ACPI_FUNCTION_ENTRY(); - - /* Length is the total descriptor length minus the header length */ - - resource_length = (acpi_rs_length) - (total_length - acpi_ut_get_resource_header_length(aml)); - - /* Length is stored differently for large and small descriptors */ - - if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) { - - /* Large descriptor -- bytes 1-2 contain the 16-bit length */ - - ACPI_MOVE_16_TO_16(&aml->large_header.resource_length, - &resource_length); - } else { - /* Small descriptor -- bits 2:0 of byte 0 contain the length */ - - aml->small_header.descriptor_type = (u8) - - /* Clear any existing length, preserving descriptor type bits */ - ((aml->small_header. - descriptor_type & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK) - - | resource_length); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_set_resource_header - * - * PARAMETERS: descriptor_type - Byte to be inserted as the type - * total_length - Length of the AML descriptor, including - * the header and length fields. - * Aml - Pointer to the raw AML descriptor - * - * RETURN: None - * - * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML - * resource descriptor, both Large and Small descriptors are - * supported automatically - * - ******************************************************************************/ - -void -acpi_rs_set_resource_header(u8 descriptor_type, - acpi_rsdesc_size total_length, - union aml_resource *aml) -{ - ACPI_FUNCTION_ENTRY(); - - /* Set the Resource Type */ - - aml->small_header.descriptor_type = descriptor_type; - - /* Set the Resource Length */ - - acpi_rs_set_resource_length(total_length, aml); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_strcpy - * - * PARAMETERS: Destination - Pointer to the destination string - * Source - Pointer to the source string - * - * RETURN: String length, including NULL terminator - * - * DESCRIPTION: Local string copy that returns the string length, saving a - * strcpy followed by a strlen. - * - ******************************************************************************/ - -static u16 acpi_rs_strcpy(char *destination, char *source) -{ - u16 i; - - ACPI_FUNCTION_ENTRY(); - - for (i = 0; source[i]; i++) { - destination[i] = source[i]; - } - - destination[i] = 0; - - /* Return string length including the NULL terminator */ - - return ((u16) (i + 1)); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_get_resource_source - * - * PARAMETERS: resource_length - Length field of the descriptor - * minimum_length - Minimum length of the descriptor (minus - * any optional fields) - * resource_source - Where the resource_source is returned - * Aml - Pointer to the raw AML descriptor - * string_ptr - (optional) where to store the actual - * resource_source string - * - * RETURN: Length of the string plus NULL terminator, rounded up to native - * word boundary - * - * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor - * to an internal resource descriptor - * - ******************************************************************************/ - -acpi_rs_length -acpi_rs_get_resource_source(acpi_rs_length resource_length, - acpi_rs_length minimum_length, - struct acpi_resource_source * resource_source, - union aml_resource * aml, char *string_ptr) -{ - acpi_rsdesc_size total_length; - u8 *aml_resource_source; - - ACPI_FUNCTION_ENTRY(); - - total_length = - resource_length + sizeof(struct aml_resource_large_header); - aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); - - /* - * resource_source is present if the length of the descriptor is longer than - * the minimum length. - * - * Note: Some resource descriptors will have an additional null, so - * we add 1 to the minimum length. - */ - if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) { - - /* Get the resource_source_index */ - - resource_source->index = aml_resource_source[0]; - - resource_source->string_ptr = string_ptr; - if (!string_ptr) { - /* - * String destination pointer is not specified; Set the String - * pointer to the end of the current resource_source structure. - */ - resource_source->string_ptr = - ACPI_ADD_PTR(char, resource_source, - sizeof(struct acpi_resource_source)); - } - - /* - * In order for the Resource length to be a multiple of the native - * word, calculate the length of the string (+1 for NULL terminator) - * and expand to the next word multiple. - * - * Zero the entire area of the buffer. - */ - total_length = (u32) - ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + 1; - total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); - - ACPI_MEMSET(resource_source->string_ptr, 0, total_length); - - /* Copy the resource_source string to the destination */ - - resource_source->string_length = - acpi_rs_strcpy(resource_source->string_ptr, - ACPI_CAST_PTR(char, - &aml_resource_source[1])); - - return ((acpi_rs_length) total_length); - } - - /* resource_source is not present */ - - resource_source->index = 0; - resource_source->string_length = 0; - resource_source->string_ptr = NULL; - return (0); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_set_resource_source - * - * PARAMETERS: Aml - Pointer to the raw AML descriptor - * minimum_length - Minimum length of the descriptor (minus - * any optional fields) - * resource_source - Internal resource_source - - * - * RETURN: Total length of the AML descriptor - * - * DESCRIPTION: Convert an optional resource_source from internal format to a - * raw AML resource descriptor - * - ******************************************************************************/ - -acpi_rsdesc_size -acpi_rs_set_resource_source(union aml_resource * aml, - acpi_rs_length minimum_length, - struct acpi_resource_source * resource_source) -{ - u8 *aml_resource_source; - acpi_rsdesc_size descriptor_length; - - ACPI_FUNCTION_ENTRY(); - - descriptor_length = minimum_length; - - /* Non-zero string length indicates presence of a resource_source */ - - if (resource_source->string_length) { - - /* Point to the end of the AML descriptor */ - - aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); - - /* Copy the resource_source_index */ - - aml_resource_source[0] = (u8) resource_source->index; - - /* Copy the resource_source string */ - - ACPI_STRCPY(ACPI_CAST_PTR(char, &aml_resource_source[1]), - resource_source->string_ptr); - - /* - * Add the length of the string (+ 1 for null terminator) to the - * final descriptor length - */ - descriptor_length += - ((acpi_rsdesc_size) resource_source->string_length + 1); - } - - /* Return the new total length of the AML descriptor */ - - return (descriptor_length); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_get_prt_method_data - * - * PARAMETERS: Node - Device node - * ret_buffer - Pointer to a buffer structure for the - * results - * - * RETURN: Status - * - * DESCRIPTION: This function is called to get the _PRT value of an object - * contained in an object specified by the handle passed in - * - * If the function fails an appropriate status will be returned - * and the contents of the callers buffer is undefined. - * - ******************************************************************************/ - -acpi_status -acpi_rs_get_prt_method_data(struct acpi_namespace_node * node, - struct acpi_buffer * ret_buffer) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE(rs_get_prt_method_data); - - /* Parameters guaranteed valid by caller */ - - /* Execute the method, no parameters */ - - status = acpi_ut_evaluate_object(node, METHOD_NAME__PRT, - ACPI_BTYPE_PACKAGE, &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Create a resource linked list from the byte stream buffer that comes - * back from the _CRS method execution. - */ - status = acpi_rs_create_pci_routing_table(obj_desc, ret_buffer); - - /* On exit, we must delete the object returned by evaluate_object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_get_crs_method_data - * - * PARAMETERS: Node - Device node - * ret_buffer - Pointer to a buffer structure for the - * results - * - * RETURN: Status - * - * DESCRIPTION: This function is called to get the _CRS value of an object - * contained in an object specified by the handle passed in - * - * If the function fails an appropriate status will be returned - * and the contents of the callers buffer is undefined. - * - ******************************************************************************/ - -acpi_status -acpi_rs_get_crs_method_data(struct acpi_namespace_node *node, - struct acpi_buffer *ret_buffer) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE(rs_get_crs_method_data); - - /* Parameters guaranteed valid by caller */ - - /* Execute the method, no parameters */ - - status = acpi_ut_evaluate_object(node, METHOD_NAME__CRS, - ACPI_BTYPE_BUFFER, &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Make the call to create a resource linked list from the - * byte stream buffer that comes back from the _CRS method - * execution. - */ - status = acpi_rs_create_resource_list(obj_desc, ret_buffer); - - /* On exit, we must delete the object returned by evaluate_object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_get_prs_method_data - * - * PARAMETERS: Node - Device node - * ret_buffer - Pointer to a buffer structure for the - * results - * - * RETURN: Status - * - * DESCRIPTION: This function is called to get the _PRS value of an object - * contained in an object specified by the handle passed in - * - * If the function fails an appropriate status will be returned - * and the contents of the callers buffer is undefined. - * - ******************************************************************************/ - -#ifdef ACPI_FUTURE_USAGE -acpi_status -acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, - struct acpi_buffer *ret_buffer) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE(rs_get_prs_method_data); - - /* Parameters guaranteed valid by caller */ - - /* Execute the method, no parameters */ - - status = acpi_ut_evaluate_object(node, METHOD_NAME__PRS, - ACPI_BTYPE_BUFFER, &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Make the call to create a resource linked list from the - * byte stream buffer that comes back from the _CRS method - * execution. - */ - status = acpi_rs_create_resource_list(obj_desc, ret_buffer); - - /* On exit, we must delete the object returned by evaluate_object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} -#endif /* ACPI_FUTURE_USAGE */ - -/******************************************************************************* - * - * FUNCTION: acpi_rs_get_method_data - * - * PARAMETERS: Handle - Handle to the containing object - * Path - Path to method, relative to Handle - * ret_buffer - Pointer to a buffer structure for the - * results - * - * RETURN: Status - * - * DESCRIPTION: This function is called to get the _CRS or _PRS value of an - * object contained in an object specified by the handle passed in - * - * If the function fails an appropriate status will be returned - * and the contents of the callers buffer is undefined. - * - ******************************************************************************/ - -acpi_status -acpi_rs_get_method_data(acpi_handle handle, - char *path, struct acpi_buffer *ret_buffer) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE(rs_get_method_data); - - /* Parameters guaranteed valid by caller */ - - /* Execute the method, no parameters */ - - status = - acpi_ut_evaluate_object(handle, path, ACPI_BTYPE_BUFFER, &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Make the call to create a resource linked list from the - * byte stream buffer that comes back from the method - * execution. - */ - status = acpi_rs_create_resource_list(obj_desc, ret_buffer); - - /* On exit, we must delete the object returned by evaluate_object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_set_srs_method_data - * - * PARAMETERS: Node - Device node - * in_buffer - Pointer to a buffer structure of the - * parameter - * - * RETURN: Status - * - * DESCRIPTION: This function is called to set the _SRS of an object contained - * in an object specified by the handle passed in - * - * If the function fails an appropriate status will be returned - * and the contents of the callers buffer is undefined. - * - * Note: Parameters guaranteed valid by caller - * - ******************************************************************************/ - -acpi_status -acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, - struct acpi_buffer *in_buffer) -{ - struct acpi_evaluate_info *info; - union acpi_operand_object *args[2]; - acpi_status status; - struct acpi_buffer buffer; - - ACPI_FUNCTION_TRACE(rs_set_srs_method_data); - - /* Allocate and initialize the evaluation information block */ - - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); - if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - info->prefix_node = node; - info->pathname = METHOD_NAME__SRS; - info->parameters = args; - info->flags = ACPI_IGNORE_RETURN_VALUE; - - /* - * The in_buffer parameter will point to a linked list of - * resource parameters. It needs to be formatted into a - * byte stream to be sent in as an input parameter to _SRS - * - * Convert the linked list into a byte stream - */ - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Create and initialize the method parameter object */ - - args[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); - if (!args[0]) { - /* - * Must free the buffer allocated above (otherwise it is freed - * later) - */ - ACPI_FREE(buffer.pointer); - status = AE_NO_MEMORY; - goto cleanup; - } - - args[0]->buffer.length = (u32) buffer.length; - args[0]->buffer.pointer = buffer.pointer; - args[0]->common.flags = AOPOBJ_DATA_VALID; - args[1] = NULL; - - /* Execute the method, no return value is expected */ - - status = acpi_ns_evaluate(info); - - /* Clean up and return the status from acpi_ns_evaluate */ - - acpi_ut_remove_reference(args[0]); - - cleanup: - ACPI_FREE(info); - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c deleted file mode 100644 index 0a274356b23e..000000000000 --- a/drivers/acpi/resources/rsxface.c +++ /dev/null @@ -1,571 +0,0 @@ -/******************************************************************************* - * - * Module Name: rsxface - Public interfaces to the resource manager - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_RESOURCES -ACPI_MODULE_NAME("rsxface") - -/* Local macros for 16,32-bit to 64-bit conversion */ -#define ACPI_COPY_FIELD(out, in, field) ((out)->field = (in)->field) -#define ACPI_COPY_ADDRESS(out, in) \ - ACPI_COPY_FIELD(out, in, resource_type); \ - ACPI_COPY_FIELD(out, in, producer_consumer); \ - ACPI_COPY_FIELD(out, in, decode); \ - ACPI_COPY_FIELD(out, in, min_address_fixed); \ - ACPI_COPY_FIELD(out, in, max_address_fixed); \ - ACPI_COPY_FIELD(out, in, info); \ - ACPI_COPY_FIELD(out, in, granularity); \ - ACPI_COPY_FIELD(out, in, minimum); \ - ACPI_COPY_FIELD(out, in, maximum); \ - ACPI_COPY_FIELD(out, in, translation_offset); \ - ACPI_COPY_FIELD(out, in, address_length); \ - ACPI_COPY_FIELD(out, in, resource_source); -/* Local prototypes */ -static acpi_status -acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context); - -static acpi_status -acpi_rs_validate_parameters(acpi_handle device_handle, - struct acpi_buffer *buffer, - struct acpi_namespace_node **return_node); - -/******************************************************************************* - * - * FUNCTION: acpi_rs_validate_parameters - * - * PARAMETERS: device_handle - Handle to a device - * Buffer - Pointer to a data buffer - * return_node - Pointer to where the device node is returned - * - * RETURN: Status - * - * DESCRIPTION: Common parameter validation for resource interfaces - * - ******************************************************************************/ - -static acpi_status -acpi_rs_validate_parameters(acpi_handle device_handle, - struct acpi_buffer *buffer, - struct acpi_namespace_node **return_node) -{ - acpi_status status; - struct acpi_namespace_node *node; - - ACPI_FUNCTION_TRACE(rs_validate_parameters); - - /* - * Must have a valid handle to an ACPI device - */ - if (!device_handle) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - node = acpi_ns_map_handle_to_node(device_handle); - if (!node) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (node->type != ACPI_TYPE_DEVICE) { - return_ACPI_STATUS(AE_TYPE); - } - - /* - * Validate the user buffer object - * - * if there is a non-zero buffer length we also need a valid pointer in - * the buffer. If it's a zero buffer length, we'll be returning the - * needed buffer size (later), so keep going. - */ - status = acpi_ut_validate_buffer(buffer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - *return_node = node; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_get_irq_routing_table - * - * PARAMETERS: device_handle - Handle to the Bus device we are querying - * ret_buffer - Pointer to a buffer to receive the - * current resources for the device - * - * RETURN: Status - * - * DESCRIPTION: This function is called to get the IRQ routing table for a - * specific bus. The caller must first acquire a handle for the - * desired bus. The routine table is placed in the buffer pointed - * to by the ret_buffer variable parameter. - * - * If the function fails an appropriate status will be returned - * and the value of ret_buffer is undefined. - * - * This function attempts to execute the _PRT method contained in - * the object indicated by the passed device_handle. - * - ******************************************************************************/ - -acpi_status -acpi_get_irq_routing_table(acpi_handle device_handle, - struct acpi_buffer *ret_buffer) -{ - acpi_status status; - struct acpi_namespace_node *node; - - ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table); - - /* Validate parameters then dispatch to internal routine */ - - status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_rs_get_prt_method_data(node, ret_buffer); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table) - -/******************************************************************************* - * - * FUNCTION: acpi_get_current_resources - * - * PARAMETERS: device_handle - Handle to the device object for the - * device we are querying - * ret_buffer - Pointer to a buffer to receive the - * current resources for the device - * - * RETURN: Status - * - * DESCRIPTION: This function is called to get the current resources for a - * specific device. The caller must first acquire a handle for - * the desired device. The resource data is placed in the buffer - * pointed to by the ret_buffer variable parameter. - * - * If the function fails an appropriate status will be returned - * and the value of ret_buffer is undefined. - * - * This function attempts to execute the _CRS method contained in - * the object indicated by the passed device_handle. - * - ******************************************************************************/ -acpi_status -acpi_get_current_resources(acpi_handle device_handle, - struct acpi_buffer *ret_buffer) -{ - acpi_status status; - struct acpi_namespace_node *node; - - ACPI_FUNCTION_TRACE(acpi_get_current_resources); - - /* Validate parameters then dispatch to internal routine */ - - status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_rs_get_crs_method_data(node, ret_buffer); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_current_resources) -#ifdef ACPI_FUTURE_USAGE -/******************************************************************************* - * - * FUNCTION: acpi_get_possible_resources - * - * PARAMETERS: device_handle - Handle to the device object for the - * device we are querying - * ret_buffer - Pointer to a buffer to receive the - * resources for the device - * - * RETURN: Status - * - * DESCRIPTION: This function is called to get a list of the possible resources - * for a specific device. The caller must first acquire a handle - * for the desired device. The resource data is placed in the - * buffer pointed to by the ret_buffer variable. - * - * If the function fails an appropriate status will be returned - * and the value of ret_buffer is undefined. - * - ******************************************************************************/ -acpi_status -acpi_get_possible_resources(acpi_handle device_handle, - struct acpi_buffer *ret_buffer) -{ - acpi_status status; - struct acpi_namespace_node *node; - - ACPI_FUNCTION_TRACE(acpi_get_possible_resources); - - /* Validate parameters then dispatch to internal routine */ - - status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_rs_get_prs_method_data(node, ret_buffer); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_possible_resources) -#endif /* ACPI_FUTURE_USAGE */ -/******************************************************************************* - * - * FUNCTION: acpi_set_current_resources - * - * PARAMETERS: device_handle - Handle to the device object for the - * device we are setting resources - * in_buffer - Pointer to a buffer containing the - * resources to be set for the device - * - * RETURN: Status - * - * DESCRIPTION: This function is called to set the current resources for a - * specific device. The caller must first acquire a handle for - * the desired device. The resource data is passed to the routine - * the buffer pointed to by the in_buffer variable. - * - ******************************************************************************/ -acpi_status -acpi_set_current_resources(acpi_handle device_handle, - struct acpi_buffer *in_buffer) -{ - acpi_status status; - struct acpi_namespace_node *node; - - ACPI_FUNCTION_TRACE(acpi_set_current_resources); - - /* Validate the buffer, don't allow zero length */ - - if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Validate parameters then dispatch to internal routine */ - - status = acpi_rs_validate_parameters(device_handle, in_buffer, &node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_rs_set_srs_method_data(node, in_buffer); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_set_current_resources) - -/****************************************************************************** - * - * FUNCTION: acpi_resource_to_address64 - * - * PARAMETERS: Resource - Pointer to a resource - * Out - Pointer to the users's return buffer - * (a struct acpi_resource_address64) - * - * RETURN: Status - * - * DESCRIPTION: If the resource is an address16, address32, or address64, - * copy it to the address64 return buffer. This saves the - * caller from having to duplicate code for different-sized - * addresses. - * - ******************************************************************************/ -acpi_status -acpi_resource_to_address64(struct acpi_resource *resource, - struct acpi_resource_address64 *out) -{ - struct acpi_resource_address16 *address16; - struct acpi_resource_address32 *address32; - - if (!resource || !out) { - return (AE_BAD_PARAMETER); - } - - /* Convert 16 or 32 address descriptor to 64 */ - - switch (resource->type) { - case ACPI_RESOURCE_TYPE_ADDRESS16: - - address16 = (struct acpi_resource_address16 *)&resource->data; - ACPI_COPY_ADDRESS(out, address16); - break; - - case ACPI_RESOURCE_TYPE_ADDRESS32: - - address32 = (struct acpi_resource_address32 *)&resource->data; - ACPI_COPY_ADDRESS(out, address32); - break; - - case ACPI_RESOURCE_TYPE_ADDRESS64: - - /* Simple copy for 64 bit source */ - - ACPI_MEMCPY(out, &resource->data, - sizeof(struct acpi_resource_address64)); - break; - - default: - return (AE_BAD_PARAMETER); - } - - return (AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_resource_to_address64) - -/******************************************************************************* - * - * FUNCTION: acpi_get_vendor_resource - * - * PARAMETERS: device_handle - Handle for the parent device object - * Name - Method name for the parent resource - * (METHOD_NAME__CRS or METHOD_NAME__PRS) - * Uuid - Pointer to the UUID to be matched. - * includes both subtype and 16-byte UUID - * ret_buffer - Where the vendor resource is returned - * - * RETURN: Status - * - * DESCRIPTION: Walk a resource template for the specified evice to find a - * vendor-defined resource that matches the supplied UUID and - * UUID subtype. Returns a struct acpi_resource of type Vendor. - * - ******************************************************************************/ -acpi_status -acpi_get_vendor_resource(acpi_handle device_handle, - char *name, - struct acpi_vendor_uuid * uuid, - struct acpi_buffer * ret_buffer) -{ - struct acpi_vendor_walk_info info; - acpi_status status; - - /* Other parameters are validated by acpi_walk_resources */ - - if (!uuid || !ret_buffer) { - return (AE_BAD_PARAMETER); - } - - info.uuid = uuid; - info.buffer = ret_buffer; - info.status = AE_NOT_EXIST; - - /* Walk the _CRS or _PRS resource list for this device */ - - status = - acpi_walk_resources(device_handle, name, - acpi_rs_match_vendor_resource, &info); - if (ACPI_FAILURE(status)) { - return (status); - } - - return (info.status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource) - -/******************************************************************************* - * - * FUNCTION: acpi_rs_match_vendor_resource - * - * PARAMETERS: acpi_walk_resource_callback - * - * RETURN: Status - * - * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID - * - ******************************************************************************/ -static acpi_status -acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) -{ - struct acpi_vendor_walk_info *info = context; - struct acpi_resource_vendor_typed *vendor; - struct acpi_buffer *buffer; - acpi_status status; - - /* Ignore all descriptors except Vendor */ - - if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) { - return (AE_OK); - } - - vendor = &resource->data.vendor_typed; - - /* - * For a valid match, these conditions must hold: - * - * 1) Length of descriptor data must be at least as long as a UUID struct - * 2) The UUID subtypes must match - * 3) The UUID data must match - */ - if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) || - (vendor->uuid_subtype != info->uuid->subtype) || - (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) { - return (AE_OK); - } - - /* Validate/Allocate/Clear caller buffer */ - - buffer = info->buffer; - status = acpi_ut_initialize_buffer(buffer, resource->length); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Found the correct resource, copy and return it */ - - ACPI_MEMCPY(buffer->pointer, resource, resource->length); - buffer->length = resource->length; - - /* Found the desired descriptor, terminate resource walk */ - - info->status = AE_OK; - return (AE_CTRL_TERMINATE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_walk_resources - * - * PARAMETERS: device_handle - Handle to the device object for the - * device we are querying - * Name - Method name of the resources we want - * (METHOD_NAME__CRS or METHOD_NAME__PRS) - * user_function - Called for each resource - * Context - Passed to user_function - * - * RETURN: Status - * - * DESCRIPTION: Retrieves the current or possible resource list for the - * specified device. The user_function is called once for - * each resource in the list. - * - ******************************************************************************/ -acpi_status -acpi_walk_resources(acpi_handle device_handle, - char *name, - acpi_walk_resource_callback user_function, void *context) -{ - acpi_status status; - struct acpi_buffer buffer; - struct acpi_resource *resource; - struct acpi_resource *resource_end; - - ACPI_FUNCTION_TRACE(acpi_walk_resources); - - /* Parameter validation */ - - if (!device_handle || !user_function || !name || - (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && - !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Get the _CRS or _PRS resource list */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_rs_get_method_data(device_handle, name, &buffer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Buffer now contains the resource list */ - - resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); - resource_end = - ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); - - /* Walk the resource list until the end_tag is found (or buffer end) */ - - while (resource < resource_end) { - - /* Sanity check the resource */ - - if (resource->type > ACPI_RESOURCE_TYPE_MAX) { - status = AE_AML_INVALID_RESOURCE_TYPE; - break; - } - - /* Invoke the user function, abort on any error returned */ - - status = user_function(resource, context); - if (ACPI_FAILURE(status)) { - if (status == AE_CTRL_TERMINATE) { - - /* This is an OK termination by the user function */ - - status = AE_OK; - } - break; - } - - /* end_tag indicates end-of-list */ - - if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { - break; - } - - /* Get the next resource descriptor */ - - resource = - ACPI_ADD_PTR(struct acpi_resource, resource, - resource->length); - } - - ACPI_FREE(buffer.pointer); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_walk_resources) diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h new file mode 100644 index 000000000000..cfaf8f5b0a14 --- /dev/null +++ b/drivers/acpi/sleep.h @@ -0,0 +1,7 @@ + +extern u8 sleep_states[]; +extern int acpi_suspend (u32 state); + +extern void acpi_enable_wakeup_device_prep(u8 sleep_state); +extern void acpi_enable_wakeup_device(u8 sleep_state); +extern void acpi_disable_wakeup_device(u8 sleep_state); diff --git a/drivers/acpi/sleep/Makefile b/drivers/acpi/sleep/Makefile deleted file mode 100644 index f1fb888c2d29..000000000000 --- a/drivers/acpi/sleep/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-y := wakeup.o -obj-y += main.o -obj-$(CONFIG_ACPI_SLEEP) += proc.o - -EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c deleted file mode 100644 index d8242772de92..000000000000 --- a/drivers/acpi/sleep/main.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * sleep.c - ACPI sleep support. - * - * Copyright (c) 2005 Alexey Starikovskiy - * Copyright (c) 2004 David Shaohua Li - * Copyright (c) 2000-2003 Patrick Mochel - * Copyright (c) 2003 Open Source Development Lab - * - * This file is released under the GPLv2. - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include "sleep.h" - -u8 sleep_states[ACPI_S_STATE_COUNT]; - -static void acpi_sleep_tts_switch(u32 acpi_state) -{ - union acpi_object in_arg = { ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &in_arg }; - acpi_status status = AE_OK; - - in_arg.integer.value = acpi_state; - status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - /* - * OS can't evaluate the _TTS object correctly. Some warning - * message will be printed. But it won't break anything. - */ - printk(KERN_NOTICE "Failure in evaluating _TTS object\n"); - } -} - -static int tts_notify_reboot(struct notifier_block *this, - unsigned long code, void *x) -{ - acpi_sleep_tts_switch(ACPI_STATE_S5); - return NOTIFY_DONE; -} - -static struct notifier_block tts_notifier = { - .notifier_call = tts_notify_reboot, - .next = NULL, - .priority = 0, -}; - -static int acpi_sleep_prepare(u32 acpi_state) -{ -#ifdef CONFIG_ACPI_SLEEP - /* do we have a wakeup address for S2 and S3? */ - if (acpi_state == ACPI_STATE_S3) { - if (!acpi_wakeup_address) { - return -EFAULT; - } - acpi_set_firmware_waking_vector( - (acpi_physical_address)acpi_wakeup_address); - - } - ACPI_FLUSH_CPU_CACHE(); - acpi_enable_wakeup_device_prep(acpi_state); -#endif - printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n", - acpi_state); - acpi_enter_sleep_state_prep(acpi_state); - return 0; -} - -#ifdef CONFIG_ACPI_SLEEP -static u32 acpi_target_sleep_state = ACPI_STATE_S0; -/* - * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the - * user to request that behavior by using the 'acpi_old_suspend_ordering' - * kernel command line option that causes the following variable to be set. - */ -static bool old_suspend_ordering; - -void __init acpi_old_suspend_ordering(void) -{ - old_suspend_ordering = true; -} - -/* - * According to the ACPI specification the BIOS should make sure that ACPI is - * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, - * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI - * on such systems during resume. Unfortunately that doesn't help in - * particularly pathological cases in which SCI_EN has to be set directly on - * resume, although the specification states very clearly that this flag is - * owned by the hardware. The set_sci_en_on_resume variable will be set in such - * cases. - */ -static bool set_sci_en_on_resume; - -/** - * acpi_pm_disable_gpes - Disable the GPEs. - */ -static int acpi_pm_disable_gpes(void) -{ - acpi_disable_all_gpes(); - return 0; -} - -/** - * __acpi_pm_prepare - Prepare the platform to enter the target state. - * - * If necessary, set the firmware waking vector and do arch-specific - * nastiness to get the wakeup code to the waking vector. - */ -static int __acpi_pm_prepare(void) -{ - int error = acpi_sleep_prepare(acpi_target_sleep_state); - - if (error) - acpi_target_sleep_state = ACPI_STATE_S0; - return error; -} - -/** - * acpi_pm_prepare - Prepare the platform to enter the target sleep - * state and disable the GPEs. - */ -static int acpi_pm_prepare(void) -{ - int error = __acpi_pm_prepare(); - - if (!error) - acpi_disable_all_gpes(); - return error; -} - -/** - * acpi_pm_finish - Instruct the platform to leave a sleep state. - * - * This is called after we wake back up (or if entering the sleep state - * failed). - */ -static void acpi_pm_finish(void) -{ - u32 acpi_state = acpi_target_sleep_state; - - if (acpi_state == ACPI_STATE_S0) - return; - - printk(KERN_INFO PREFIX "Waking up from system sleep state S%d\n", - acpi_state); - acpi_disable_wakeup_device(acpi_state); - acpi_leave_sleep_state(acpi_state); - - /* reset firmware waking vector */ - acpi_set_firmware_waking_vector((acpi_physical_address) 0); - - acpi_target_sleep_state = ACPI_STATE_S0; -} - -/** - * acpi_pm_end - Finish up suspend sequence. - */ -static void acpi_pm_end(void) -{ - /* - * This is necessary in case acpi_pm_finish() is not called during a - * failing transition to a sleep state. - */ - acpi_target_sleep_state = ACPI_STATE_S0; - acpi_sleep_tts_switch(acpi_target_sleep_state); -} -#else /* !CONFIG_ACPI_SLEEP */ -#define acpi_target_sleep_state ACPI_STATE_S0 -#endif /* CONFIG_ACPI_SLEEP */ - -#ifdef CONFIG_SUSPEND -extern void do_suspend_lowlevel(void); - -static u32 acpi_suspend_states[] = { - [PM_SUSPEND_ON] = ACPI_STATE_S0, - [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, - [PM_SUSPEND_MEM] = ACPI_STATE_S3, - [PM_SUSPEND_MAX] = ACPI_STATE_S5 -}; - -/** - * acpi_suspend_begin - Set the target system sleep state to the state - * associated with given @pm_state, if supported. - */ -static int acpi_suspend_begin(suspend_state_t pm_state) -{ - u32 acpi_state = acpi_suspend_states[pm_state]; - int error = 0; - - if (sleep_states[acpi_state]) { - acpi_target_sleep_state = acpi_state; - acpi_sleep_tts_switch(acpi_target_sleep_state); - } else { - printk(KERN_ERR "ACPI does not support this state: %d\n", - pm_state); - error = -ENOSYS; - } - return error; -} - -/** - * acpi_suspend_enter - Actually enter a sleep state. - * @pm_state: ignored - * - * Flush caches and go to sleep. For STR we have to call arch-specific - * assembly, which in turn call acpi_enter_sleep_state(). - * It's unfortunate, but it works. Please fix if you're feeling frisky. - */ -static int acpi_suspend_enter(suspend_state_t pm_state) -{ - acpi_status status = AE_OK; - unsigned long flags = 0; - u32 acpi_state = acpi_target_sleep_state; - - ACPI_FLUSH_CPU_CACHE(); - - /* Do arch specific saving of state. */ - if (acpi_state == ACPI_STATE_S3) { - int error = acpi_save_state_mem(); - - if (error) - return error; - } - - local_irq_save(flags); - acpi_enable_wakeup_device(acpi_state); - switch (acpi_state) { - case ACPI_STATE_S1: - barrier(); - status = acpi_enter_sleep_state(acpi_state); - break; - - case ACPI_STATE_S3: - do_suspend_lowlevel(); - break; - } - - /* If ACPI is not enabled by the BIOS, we need to enable it here. */ - if (set_sci_en_on_resume) - acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1); - else - acpi_enable(); - - /* Reprogram control registers and execute _BFS */ - acpi_leave_sleep_state_prep(acpi_state); - - /* ACPI 3.0 specs (P62) says that it's the responsibility - * of the OSPM to clear the status bit [ implying that the - * POWER_BUTTON event should not reach userspace ] - */ - if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) - acpi_clear_event(ACPI_EVENT_POWER_BUTTON); - - /* - * Disable and clear GPE status before interrupt is enabled. Some GPEs - * (like wakeup GPE) haven't handler, this can avoid such GPE misfire. - * acpi_leave_sleep_state will reenable specific GPEs later - */ - acpi_disable_all_gpes(); - - local_irq_restore(flags); - printk(KERN_DEBUG "Back to C!\n"); - - /* restore processor state */ - if (acpi_state == ACPI_STATE_S3) - acpi_restore_state_mem(); - - return ACPI_SUCCESS(status) ? 0 : -EFAULT; -} - -static int acpi_suspend_state_valid(suspend_state_t pm_state) -{ - u32 acpi_state; - - switch (pm_state) { - case PM_SUSPEND_ON: - case PM_SUSPEND_STANDBY: - case PM_SUSPEND_MEM: - acpi_state = acpi_suspend_states[pm_state]; - - return sleep_states[acpi_state]; - default: - return 0; - } -} - -static struct platform_suspend_ops acpi_suspend_ops = { - .valid = acpi_suspend_state_valid, - .begin = acpi_suspend_begin, - .prepare = acpi_pm_prepare, - .enter = acpi_suspend_enter, - .finish = acpi_pm_finish, - .end = acpi_pm_end, -}; - -/** - * acpi_suspend_begin_old - Set the target system sleep state to the - * state associated with given @pm_state, if supported, and - * execute the _PTS control method. This function is used if the - * pre-ACPI 2.0 suspend ordering has been requested. - */ -static int acpi_suspend_begin_old(suspend_state_t pm_state) -{ - int error = acpi_suspend_begin(pm_state); - - if (!error) - error = __acpi_pm_prepare(); - return error; -} - -/* - * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has - * been requested. - */ -static struct platform_suspend_ops acpi_suspend_ops_old = { - .valid = acpi_suspend_state_valid, - .begin = acpi_suspend_begin_old, - .prepare = acpi_pm_disable_gpes, - .enter = acpi_suspend_enter, - .finish = acpi_pm_finish, - .end = acpi_pm_end, - .recover = acpi_pm_finish, -}; - -static int __init init_old_suspend_ordering(const struct dmi_system_id *d) -{ - old_suspend_ordering = true; - return 0; -} - -static int __init init_set_sci_en_on_resume(const struct dmi_system_id *d) -{ - set_sci_en_on_resume = true; - return 0; -} - -static struct dmi_system_id __initdata acpisleep_dmi_table[] = { - { - .callback = init_old_suspend_ordering, - .ident = "Abit KN9 (nForce4 variant)", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"), - DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "HP xw4600 Workstation", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Apple MacBook 1,1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Apple MacMini 1,1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), - }, - }, - {}, -}; -#endif /* CONFIG_SUSPEND */ - -#ifdef CONFIG_HIBERNATION -static unsigned long s4_hardware_signature; -static struct acpi_table_facs *facs; -static bool nosigcheck; - -void __init acpi_no_s4_hw_signature(void) -{ - nosigcheck = true; -} - -static int acpi_hibernation_begin(void) -{ - acpi_target_sleep_state = ACPI_STATE_S4; - acpi_sleep_tts_switch(acpi_target_sleep_state); - return 0; -} - -static int acpi_hibernation_enter(void) -{ - acpi_status status = AE_OK; - unsigned long flags = 0; - - ACPI_FLUSH_CPU_CACHE(); - - local_irq_save(flags); - acpi_enable_wakeup_device(ACPI_STATE_S4); - /* This shouldn't return. If it returns, we have a problem */ - status = acpi_enter_sleep_state(ACPI_STATE_S4); - /* Reprogram control registers and execute _BFS */ - acpi_leave_sleep_state_prep(ACPI_STATE_S4); - local_irq_restore(flags); - - return ACPI_SUCCESS(status) ? 0 : -EFAULT; -} - -static void acpi_hibernation_leave(void) -{ - /* - * If ACPI is not enabled by the BIOS and the boot kernel, we need to - * enable it here. - */ - acpi_enable(); - /* Reprogram control registers and execute _BFS */ - acpi_leave_sleep_state_prep(ACPI_STATE_S4); - /* Check the hardware signature */ - if (facs && s4_hardware_signature != facs->hardware_signature) { - printk(KERN_EMERG "ACPI: Hardware changed while hibernated, " - "cannot resume!\n"); - panic("ACPI S4 hardware signature mismatch"); - } -} - -static void acpi_pm_enable_gpes(void) -{ - acpi_enable_all_runtime_gpes(); -} - -static struct platform_hibernation_ops acpi_hibernation_ops = { - .begin = acpi_hibernation_begin, - .end = acpi_pm_end, - .pre_snapshot = acpi_pm_prepare, - .finish = acpi_pm_finish, - .prepare = acpi_pm_prepare, - .enter = acpi_hibernation_enter, - .leave = acpi_hibernation_leave, - .pre_restore = acpi_pm_disable_gpes, - .restore_cleanup = acpi_pm_enable_gpes, -}; - -/** - * acpi_hibernation_begin_old - Set the target system sleep state to - * ACPI_STATE_S4 and execute the _PTS control method. This - * function is used if the pre-ACPI 2.0 suspend ordering has been - * requested. - */ -static int acpi_hibernation_begin_old(void) -{ - int error; - /* - * The _TTS object should always be evaluated before the _PTS object. - * When the old_suspended_ordering is true, the _PTS object is - * evaluated in the acpi_sleep_prepare. - */ - acpi_sleep_tts_switch(ACPI_STATE_S4); - - error = acpi_sleep_prepare(ACPI_STATE_S4); - - if (!error) - acpi_target_sleep_state = ACPI_STATE_S4; - return error; -} - -/* - * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has - * been requested. - */ -static struct platform_hibernation_ops acpi_hibernation_ops_old = { - .begin = acpi_hibernation_begin_old, - .end = acpi_pm_end, - .pre_snapshot = acpi_pm_disable_gpes, - .finish = acpi_pm_finish, - .prepare = acpi_pm_disable_gpes, - .enter = acpi_hibernation_enter, - .leave = acpi_hibernation_leave, - .pre_restore = acpi_pm_disable_gpes, - .restore_cleanup = acpi_pm_enable_gpes, - .recover = acpi_pm_finish, -}; -#endif /* CONFIG_HIBERNATION */ - -int acpi_suspend(u32 acpi_state) -{ - suspend_state_t states[] = { - [1] = PM_SUSPEND_STANDBY, - [3] = PM_SUSPEND_MEM, - [5] = PM_SUSPEND_MAX - }; - - if (acpi_state < 6 && states[acpi_state]) - return pm_suspend(states[acpi_state]); - if (acpi_state == 4) - return hibernate(); - return -EINVAL; -} - -#ifdef CONFIG_PM_SLEEP -/** - * acpi_pm_device_sleep_state - return preferred power state of ACPI device - * in the system sleep state given by %acpi_target_sleep_state - * @dev: device to examine; its driver model wakeup flags control - * whether it should be able to wake up the system - * @d_min_p: used to store the upper limit of allowed states range - * Return value: preferred power state of the device on success, -ENODEV on - * failure (ie. if there's no 'struct acpi_device' for @dev) - * - * Find the lowest power (highest number) ACPI device power state that - * device @dev can be in while the system is in the sleep state represented - * by %acpi_target_sleep_state. If @wake is nonzero, the device should be - * able to wake up the system from this sleep state. If @d_min_p is set, - * the highest power (lowest number) device power state of @dev allowed - * in this system sleep state is stored at the location pointed to by it. - * - * The caller must ensure that @dev is valid before using this function. - * The caller is also responsible for figuring out if the device is - * supposed to be able to wake up the system and passing this information - * via @wake. - */ - -int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) -{ - acpi_handle handle = DEVICE_ACPI_HANDLE(dev); - struct acpi_device *adev; - char acpi_method[] = "_SxD"; - unsigned long long d_min, d_max; - - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { - printk(KERN_DEBUG "ACPI handle has no context!\n"); - return -ENODEV; - } - - acpi_method[2] = '0' + acpi_target_sleep_state; - /* - * If the sleep state is S0, we will return D3, but if the device has - * _S0W, we will use the value from _S0W - */ - d_min = ACPI_STATE_D0; - d_max = ACPI_STATE_D3; - - /* - * If present, _SxD methods return the minimum D-state (highest power - * state) we can use for the corresponding S-states. Otherwise, the - * minimum D-state is D0 (ACPI 3.x). - * - * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer - * provided -- that's our fault recovery, we ignore retval. - */ - if (acpi_target_sleep_state > ACPI_STATE_S0) - acpi_evaluate_integer(handle, acpi_method, NULL, &d_min); - - /* - * If _PRW says we can wake up the system from the target sleep state, - * the D-state returned by _SxD is sufficient for that (we assume a - * wakeup-aware driver if wake is set). Still, if _SxW exists - * (ACPI 3.x), it should return the maximum (lowest power) D-state that - * can wake the system. _S0W may be valid, too. - */ - if (acpi_target_sleep_state == ACPI_STATE_S0 || - (device_may_wakeup(dev) && adev->wakeup.state.enabled && - adev->wakeup.sleep_state <= acpi_target_sleep_state)) { - acpi_status status; - - acpi_method[3] = 'W'; - status = acpi_evaluate_integer(handle, acpi_method, NULL, - &d_max); - if (ACPI_FAILURE(status)) { - d_max = d_min; - } else if (d_max < d_min) { - /* Warn the user of the broken DSDT */ - printk(KERN_WARNING "ACPI: Wrong value from %s\n", - acpi_method); - /* Sanitize it */ - d_min = d_max; - } - } - - if (d_min_p) - *d_min_p = d_min; - return d_max; -} - -/** - * acpi_pm_device_sleep_wake - enable or disable the system wake-up - * capability of given device - * @dev: device to handle - * @enable: 'true' - enable, 'false' - disable the wake-up capability - */ -int acpi_pm_device_sleep_wake(struct device *dev, bool enable) -{ - acpi_handle handle; - struct acpi_device *adev; - - if (!device_may_wakeup(dev)) - return -EINVAL; - - handle = DEVICE_ACPI_HANDLE(dev); - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { - printk(KERN_DEBUG "ACPI handle has no context!\n"); - return -ENODEV; - } - - return enable ? - acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) : - acpi_disable_wakeup_device_power(adev); -} -#endif - -static void acpi_power_off_prepare(void) -{ - /* Prepare to power off the system */ - acpi_sleep_prepare(ACPI_STATE_S5); - acpi_disable_all_gpes(); -} - -static void acpi_power_off(void) -{ - /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ - printk("%s called\n", __func__); - local_irq_disable(); - acpi_enable_wakeup_device(ACPI_STATE_S5); - acpi_enter_sleep_state(ACPI_STATE_S5); -} - -int __init acpi_sleep_init(void) -{ - acpi_status status; - u8 type_a, type_b; -#ifdef CONFIG_SUSPEND - int i = 0; - - dmi_check_system(acpisleep_dmi_table); -#endif - - if (acpi_disabled) - return 0; - - sleep_states[ACPI_STATE_S0] = 1; - printk(KERN_INFO PREFIX "(supports S0"); - -#ifdef CONFIG_SUSPEND - for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) { - status = acpi_get_sleep_type_data(i, &type_a, &type_b); - if (ACPI_SUCCESS(status)) { - sleep_states[i] = 1; - printk(" S%d", i); - } - } - - suspend_set_ops(old_suspend_ordering ? - &acpi_suspend_ops_old : &acpi_suspend_ops); -#endif - -#ifdef CONFIG_HIBERNATION - status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); - if (ACPI_SUCCESS(status)) { - hibernation_set_ops(old_suspend_ordering ? - &acpi_hibernation_ops_old : &acpi_hibernation_ops); - sleep_states[ACPI_STATE_S4] = 1; - printk(" S4"); - if (!nosigcheck) { - acpi_get_table(ACPI_SIG_FACS, 1, - (struct acpi_table_header **)&facs); - if (facs) - s4_hardware_signature = - facs->hardware_signature; - } - } -#endif - status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); - if (ACPI_SUCCESS(status)) { - sleep_states[ACPI_STATE_S5] = 1; - printk(" S5"); - pm_power_off_prepare = acpi_power_off_prepare; - pm_power_off = acpi_power_off; - } - printk(")\n"); - /* - * Register the tts_notifier to reboot notifier list so that the _TTS - * object can also be evaluated when the system enters S5. - */ - register_reboot_notifier(&tts_notifier); - return 0; -} diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c deleted file mode 100644 index 1c4851ff2657..000000000000 --- a/drivers/acpi/sleep/proc.c +++ /dev/null @@ -1,520 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -#ifdef CONFIG_X86 -#include -#endif - -#include "sleep.h" - -#define _COMPONENT ACPI_SYSTEM_COMPONENT - -/* - * this file provides support for: - * /proc/acpi/sleep - * /proc/acpi/alarm - * /proc/acpi/wakeup - */ - -ACPI_MODULE_NAME("sleep") -#ifdef CONFIG_ACPI_PROCFS -static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset) -{ - int i; - - for (i = 0; i <= ACPI_STATE_S5; i++) { - if (sleep_states[i]) { - seq_printf(seq, "S%d ", i); - } - } - - seq_puts(seq, "\n"); - - return 0; -} - -static int acpi_system_sleep_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_system_sleep_seq_show, PDE(inode)->data); -} - -static ssize_t -acpi_system_write_sleep(struct file *file, - const char __user * buffer, size_t count, loff_t * ppos) -{ - char str[12]; - u32 state = 0; - int error = 0; - - if (count > sizeof(str) - 1) - goto Done; - memset(str, 0, sizeof(str)); - if (copy_from_user(str, buffer, count)) - return -EFAULT; - - /* Check for S4 bios request */ - if (!strcmp(str, "4b")) { - error = acpi_suspend(4); - goto Done; - } - state = simple_strtoul(str, NULL, 0); -#ifdef CONFIG_HIBERNATION - if (state == 4) { - error = hibernate(); - goto Done; - } -#endif - error = acpi_suspend(state); - Done: - return error ? error : count; -} -#endif /* CONFIG_ACPI_PROCFS */ - -#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || !defined(CONFIG_X86) -/* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */ -#else -#define HAVE_ACPI_LEGACY_ALARM -#endif - -#ifdef HAVE_ACPI_LEGACY_ALARM - -static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) -{ - u32 sec, min, hr; - u32 day, mo, yr, cent = 0; - unsigned char rtc_control = 0; - unsigned long flags; - - spin_lock_irqsave(&rtc_lock, flags); - - sec = CMOS_READ(RTC_SECONDS_ALARM); - min = CMOS_READ(RTC_MINUTES_ALARM); - hr = CMOS_READ(RTC_HOURS_ALARM); - rtc_control = CMOS_READ(RTC_CONTROL); - - /* If we ever get an FACP with proper values... */ - if (acpi_gbl_FADT.day_alarm) - /* ACPI spec: only low 6 its should be cared */ - day = CMOS_READ(acpi_gbl_FADT.day_alarm) & 0x3F; - else - day = CMOS_READ(RTC_DAY_OF_MONTH); - if (acpi_gbl_FADT.month_alarm) - mo = CMOS_READ(acpi_gbl_FADT.month_alarm); - else - mo = CMOS_READ(RTC_MONTH); - if (acpi_gbl_FADT.century) - cent = CMOS_READ(acpi_gbl_FADT.century); - - yr = CMOS_READ(RTC_YEAR); - - spin_unlock_irqrestore(&rtc_lock, flags); - - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - sec = bcd2bin(sec); - min = bcd2bin(min); - hr = bcd2bin(hr); - day = bcd2bin(day); - mo = bcd2bin(mo); - yr = bcd2bin(yr); - cent = bcd2bin(cent); - } - - /* we're trusting the FADT (see above) */ - if (!acpi_gbl_FADT.century) - /* If we're not trusting the FADT, we should at least make it - * right for _this_ century... ehm, what is _this_ century? - * - * TBD: - * ASAP: find piece of code in the kernel, e.g. star tracker driver, - * which we can trust to determine the century correctly. Atom - * watch driver would be nice, too... - * - * if that has not happened, change for first release in 2050: - * if (yr<50) - * yr += 2100; - * else - * yr += 2000; // current line of code - * - * if that has not happened either, please do on 2099/12/31:23:59:59 - * s/2000/2100 - * - */ - yr += 2000; - else - yr += cent * 100; - - seq_printf(seq, "%4.4u-", yr); - (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo); - (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day); - (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr); - (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min); - (sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec); - - return 0; -} - -static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_system_alarm_seq_show, PDE(inode)->data); -} - -static int get_date_field(char **p, u32 * value) -{ - char *next = NULL; - char *string_end = NULL; - int result = -EINVAL; - - /* - * Try to find delimeter, only to insert null. The end of the - * string won't have one, but is still valid. - */ - if (*p == NULL) - return result; - - next = strpbrk(*p, "- :"); - if (next) - *next++ = '\0'; - - *value = simple_strtoul(*p, &string_end, 10); - - /* Signal success if we got a good digit */ - if (string_end != *p) - result = 0; - - if (next) - *p = next; - else - *p = NULL; - - return result; -} - -/* Read a possibly BCD register, always return binary */ -static u32 cmos_bcd_read(int offset, int rtc_control) -{ - u32 val = CMOS_READ(offset); - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - val = bcd2bin(val); - return val; -} - -/* Write binary value into possibly BCD register */ -static void cmos_bcd_write(u32 val, int offset, int rtc_control) -{ - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - val = bin2bcd(val); - CMOS_WRITE(val, offset); -} - -static ssize_t -acpi_system_write_alarm(struct file *file, - const char __user * buffer, size_t count, loff_t * ppos) -{ - int result = 0; - char alarm_string[30] = { '\0' }; - char *p = alarm_string; - u32 sec, min, hr, day, mo, yr; - int adjust = 0; - unsigned char rtc_control = 0; - - if (count > sizeof(alarm_string) - 1) - return -EINVAL; - - if (copy_from_user(alarm_string, buffer, count)) - return -EFAULT; - - alarm_string[count] = '\0'; - - /* check for time adjustment */ - if (alarm_string[0] == '+') { - p++; - adjust = 1; - } - - if ((result = get_date_field(&p, &yr))) - goto end; - if ((result = get_date_field(&p, &mo))) - goto end; - if ((result = get_date_field(&p, &day))) - goto end; - if ((result = get_date_field(&p, &hr))) - goto end; - if ((result = get_date_field(&p, &min))) - goto end; - if ((result = get_date_field(&p, &sec))) - goto end; - - spin_lock_irq(&rtc_lock); - - rtc_control = CMOS_READ(RTC_CONTROL); - - if (adjust) { - yr += cmos_bcd_read(RTC_YEAR, rtc_control); - mo += cmos_bcd_read(RTC_MONTH, rtc_control); - day += cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control); - hr += cmos_bcd_read(RTC_HOURS, rtc_control); - min += cmos_bcd_read(RTC_MINUTES, rtc_control); - sec += cmos_bcd_read(RTC_SECONDS, rtc_control); - } - - spin_unlock_irq(&rtc_lock); - - if (sec > 59) { - min += sec/60; - sec = sec%60; - } - if (min > 59) { - hr += min/60; - min = min%60; - } - if (hr > 23) { - day += hr/24; - hr = hr%24; - } - if (day > 31) { - mo += day/32; - day = day%32; - } - if (mo > 12) { - yr += mo/13; - mo = mo%13; - } - - spin_lock_irq(&rtc_lock); - /* - * Disable alarm interrupt before setting alarm timer or else - * when ACPI_EVENT_RTC is enabled, a spurious ACPI interrupt occurs - */ - rtc_control &= ~RTC_AIE; - CMOS_WRITE(rtc_control, RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - - /* write the fields the rtc knows about */ - cmos_bcd_write(hr, RTC_HOURS_ALARM, rtc_control); - cmos_bcd_write(min, RTC_MINUTES_ALARM, rtc_control); - cmos_bcd_write(sec, RTC_SECONDS_ALARM, rtc_control); - - /* - * If the system supports an enhanced alarm it will have non-zero - * offsets into the CMOS RAM here -- which for some reason are pointing - * to the RTC area of memory. - */ - if (acpi_gbl_FADT.day_alarm) - cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control); - if (acpi_gbl_FADT.month_alarm) - cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control); - if (acpi_gbl_FADT.century) { - if (adjust) - yr += cmos_bcd_read(acpi_gbl_FADT.century, rtc_control) * 100; - cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control); - } - /* enable the rtc alarm interrupt */ - rtc_control |= RTC_AIE; - CMOS_WRITE(rtc_control, RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - - spin_unlock_irq(&rtc_lock); - - acpi_clear_event(ACPI_EVENT_RTC); - acpi_enable_event(ACPI_EVENT_RTC, 0); - - *ppos += count; - - result = 0; - end: - return result ? result : count; -} -#endif /* HAVE_ACPI_LEGACY_ALARM */ - -extern struct list_head acpi_wakeup_device_list; -extern spinlock_t acpi_device_lock; - -static int -acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) -{ - struct list_head *node, *next; - - seq_printf(seq, "Device\tS-state\t Status Sysfs node\n"); - - spin_lock(&acpi_device_lock); - list_for_each_safe(node, next, &acpi_wakeup_device_list) { - struct acpi_device *dev = - container_of(node, struct acpi_device, wakeup_list); - struct device *ldev; - - if (!dev->wakeup.flags.valid) - continue; - spin_unlock(&acpi_device_lock); - - ldev = acpi_get_physical_device(dev->handle); - seq_printf(seq, "%s\t S%d\t%c%-8s ", - dev->pnp.bus_id, - (u32) dev->wakeup.sleep_state, - dev->wakeup.flags.run_wake ? '*' : ' ', - dev->wakeup.state.enabled ? "enabled" : "disabled"); - if (ldev) - seq_printf(seq, "%s:%s", - ldev->bus ? ldev->bus->name : "no-bus", - dev_name(ldev)); - seq_printf(seq, "\n"); - put_device(ldev); - - spin_lock(&acpi_device_lock); - } - spin_unlock(&acpi_device_lock); - return 0; -} - -static void physical_device_enable_wakeup(struct acpi_device *adev) -{ - struct device *dev = acpi_get_physical_device(adev->handle); - - if (dev && device_can_wakeup(dev)) - device_set_wakeup_enable(dev, adev->wakeup.state.enabled); -} - -static ssize_t -acpi_system_write_wakeup_device(struct file *file, - const char __user * buffer, - size_t count, loff_t * ppos) -{ - struct list_head *node, *next; - char strbuf[5]; - char str[5] = ""; - int len = count; - struct acpi_device *found_dev = NULL; - - if (len > 4) - len = 4; - - if (copy_from_user(strbuf, buffer, len)) - return -EFAULT; - strbuf[len] = '\0'; - sscanf(strbuf, "%s", str); - - spin_lock(&acpi_device_lock); - list_for_each_safe(node, next, &acpi_wakeup_device_list) { - struct acpi_device *dev = - container_of(node, struct acpi_device, wakeup_list); - if (!dev->wakeup.flags.valid) - continue; - - if (!strncmp(dev->pnp.bus_id, str, 4)) { - dev->wakeup.state.enabled = - dev->wakeup.state.enabled ? 0 : 1; - found_dev = dev; - break; - } - } - if (found_dev) { - physical_device_enable_wakeup(found_dev); - list_for_each_safe(node, next, &acpi_wakeup_device_list) { - struct acpi_device *dev = container_of(node, - struct - acpi_device, - wakeup_list); - - if ((dev != found_dev) && - (dev->wakeup.gpe_number == - found_dev->wakeup.gpe_number) - && (dev->wakeup.gpe_device == - found_dev->wakeup.gpe_device)) { - printk(KERN_WARNING - "ACPI: '%s' and '%s' have the same GPE, " - "can't disable/enable one seperately\n", - dev->pnp.bus_id, found_dev->pnp.bus_id); - dev->wakeup.state.enabled = - found_dev->wakeup.state.enabled; - physical_device_enable_wakeup(dev); - } - } - } - spin_unlock(&acpi_device_lock); - return count; -} - -static int -acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_system_wakeup_device_seq_show, - PDE(inode)->data); -} - -static const struct file_operations acpi_system_wakeup_device_fops = { - .owner = THIS_MODULE, - .open = acpi_system_wakeup_device_open_fs, - .read = seq_read, - .write = acpi_system_write_wakeup_device, - .llseek = seq_lseek, - .release = single_release, -}; - -#ifdef CONFIG_ACPI_PROCFS -static const struct file_operations acpi_system_sleep_fops = { - .owner = THIS_MODULE, - .open = acpi_system_sleep_open_fs, - .read = seq_read, - .write = acpi_system_write_sleep, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* CONFIG_ACPI_PROCFS */ - -#ifdef HAVE_ACPI_LEGACY_ALARM -static const struct file_operations acpi_system_alarm_fops = { - .owner = THIS_MODULE, - .open = acpi_system_alarm_open_fs, - .read = seq_read, - .write = acpi_system_write_alarm, - .llseek = seq_lseek, - .release = single_release, -}; - -static u32 rtc_handler(void *context) -{ - acpi_clear_event(ACPI_EVENT_RTC); - acpi_disable_event(ACPI_EVENT_RTC, 0); - - return ACPI_INTERRUPT_HANDLED; -} -#endif /* HAVE_ACPI_LEGACY_ALARM */ - -static int __init acpi_sleep_proc_init(void) -{ - if (acpi_disabled) - return 0; - -#ifdef CONFIG_ACPI_PROCFS - /* 'sleep' [R/W] */ - proc_create("sleep", S_IFREG | S_IRUGO | S_IWUSR, - acpi_root_dir, &acpi_system_sleep_fops); -#endif /* CONFIG_ACPI_PROCFS */ - -#ifdef HAVE_ACPI_LEGACY_ALARM - /* 'alarm' [R/W] */ - proc_create("alarm", S_IFREG | S_IRUGO | S_IWUSR, - acpi_root_dir, &acpi_system_alarm_fops); - - acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); - /* - * Disable the RTC event after installing RTC handler. - * Only when RTC alarm is set will it be enabled. - */ - acpi_clear_event(ACPI_EVENT_RTC); - acpi_disable_event(ACPI_EVENT_RTC, 0); -#endif /* HAVE_ACPI_LEGACY_ALARM */ - - /* 'wakeup device' [R/W] */ - proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR, - acpi_root_dir, &acpi_system_wakeup_device_fops); - - return 0; -} - -late_initcall(acpi_sleep_proc_init); diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h deleted file mode 100644 index cfaf8f5b0a14..000000000000 --- a/drivers/acpi/sleep/sleep.h +++ /dev/null @@ -1,7 +0,0 @@ - -extern u8 sleep_states[]; -extern int acpi_suspend (u32 state); - -extern void acpi_enable_wakeup_device_prep(u8 sleep_state); -extern void acpi_enable_wakeup_device(u8 sleep_state); -extern void acpi_disable_wakeup_device(u8 sleep_state); diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c deleted file mode 100644 index 2d34806d45dd..000000000000 --- a/drivers/acpi/sleep/wakeup.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * wakeup.c - support wakeup devices - * Copyright (C) 2004 Li Shaohua - */ - -#include -#include -#include -#include -#include -#include "sleep.h" - -#define _COMPONENT ACPI_SYSTEM_COMPONENT -ACPI_MODULE_NAME("wakeup_devices") - -extern struct list_head acpi_wakeup_device_list; -extern spinlock_t acpi_device_lock; - -/** - * acpi_enable_wakeup_device_prep - prepare wakeup devices - * @sleep_state: ACPI state - * Enable all wakup devices power if the devices' wakeup level - * is higher than requested sleep level - */ - -void acpi_enable_wakeup_device_prep(u8 sleep_state) -{ - struct list_head *node, *next; - - spin_lock(&acpi_device_lock); - list_for_each_safe(node, next, &acpi_wakeup_device_list) { - struct acpi_device *dev = container_of(node, - struct acpi_device, - wakeup_list); - - if (!dev->wakeup.flags.valid || - !dev->wakeup.state.enabled || - (sleep_state > (u32) dev->wakeup.sleep_state)) - continue; - - spin_unlock(&acpi_device_lock); - acpi_enable_wakeup_device_power(dev, sleep_state); - spin_lock(&acpi_device_lock); - } - spin_unlock(&acpi_device_lock); -} - -/** - * acpi_enable_wakeup_device - enable wakeup devices - * @sleep_state: ACPI state - * Enable all wakup devices's GPE - */ -void acpi_enable_wakeup_device(u8 sleep_state) -{ - struct list_head *node, *next; - - /* - * Caution: this routine must be invoked when interrupt is disabled - * Refer ACPI2.0: P212 - */ - spin_lock(&acpi_device_lock); - list_for_each_safe(node, next, &acpi_wakeup_device_list) { - struct acpi_device *dev = - container_of(node, struct acpi_device, wakeup_list); - - if (!dev->wakeup.flags.valid) - continue; - - /* If users want to disable run-wake GPE, - * we only disable it for wake and leave it for runtime - */ - if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared) - || sleep_state > (u32) dev->wakeup.sleep_state) { - if (dev->wakeup.flags.run_wake) { - spin_unlock(&acpi_device_lock); - /* set_gpe_type will disable GPE, leave it like that */ - acpi_set_gpe_type(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, - ACPI_GPE_TYPE_RUNTIME); - spin_lock(&acpi_device_lock); - } - continue; - } - spin_unlock(&acpi_device_lock); - if (!dev->wakeup.flags.run_wake) - acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number); - spin_lock(&acpi_device_lock); - } - spin_unlock(&acpi_device_lock); -} - -/** - * acpi_disable_wakeup_device - disable devices' wakeup capability - * @sleep_state: ACPI state - * Disable all wakup devices's GPE and wakeup capability - */ -void acpi_disable_wakeup_device(u8 sleep_state) -{ - struct list_head *node, *next; - - spin_lock(&acpi_device_lock); - list_for_each_safe(node, next, &acpi_wakeup_device_list) { - struct acpi_device *dev = - container_of(node, struct acpi_device, wakeup_list); - - if (!dev->wakeup.flags.valid) - continue; - - if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared) - || sleep_state > (u32) dev->wakeup.sleep_state) { - if (dev->wakeup.flags.run_wake) { - spin_unlock(&acpi_device_lock); - acpi_set_gpe_type(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, - ACPI_GPE_TYPE_WAKE_RUN); - /* Re-enable it, since set_gpe_type will disable it */ - acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number); - spin_lock(&acpi_device_lock); - } - continue; - } - - spin_unlock(&acpi_device_lock); - acpi_disable_wakeup_device_power(dev); - /* Never disable run-wake GPE */ - if (!dev->wakeup.flags.run_wake) { - acpi_disable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number); - acpi_clear_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_NOT_ISR); - } - spin_lock(&acpi_device_lock); - } - spin_unlock(&acpi_device_lock); -} - -static int __init acpi_wakeup_device_init(void) -{ - struct list_head *node, *next; - - if (acpi_disabled) - return 0; - - spin_lock(&acpi_device_lock); - list_for_each_safe(node, next, &acpi_wakeup_device_list) { - struct acpi_device *dev = container_of(node, - struct acpi_device, - wakeup_list); - /* In case user doesn't load button driver */ - if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled) - continue; - spin_unlock(&acpi_device_lock); - acpi_set_gpe_type(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, - ACPI_GPE_TYPE_WAKE_RUN); - acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number); - dev->wakeup.state.enabled = 1; - spin_lock(&acpi_device_lock); - } - spin_unlock(&acpi_device_lock); - return 0; -} - -late_initcall(acpi_wakeup_device_init); diff --git a/drivers/acpi/tables/Makefile b/drivers/acpi/tables/Makefile deleted file mode 100644 index 7385efa61622..000000000000 --- a/drivers/acpi/tables/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o - -EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c deleted file mode 100644 index 87f22e68c6d6..000000000000 --- a/drivers/acpi/tables/tbfadt.c +++ /dev/null @@ -1,610 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbfadt - FADT table utilities - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_TABLES -ACPI_MODULE_NAME("tbfadt") - -/* Local prototypes */ -static inline void -acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 space_id, u8 byte_width, u64 address); - -static void acpi_tb_convert_fadt(void); - -static void acpi_tb_validate_fadt(void); - -/* Table for conversion of FADT to common internal format and FADT validation */ - -typedef struct acpi_fadt_info { - char *name; - u8 address64; - u8 address32; - u8 length; - u8 default_length; - u8 type; - -} acpi_fadt_info; - -#define ACPI_FADT_REQUIRED 1 -#define ACPI_FADT_SEPARATE_LENGTH 2 - -static struct acpi_fadt_info fadt_info_table[] = { - {"Pm1aEventBlock", - ACPI_FADT_OFFSET(xpm1a_event_block), - ACPI_FADT_OFFSET(pm1a_event_block), - ACPI_FADT_OFFSET(pm1_event_length), - ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ - ACPI_FADT_REQUIRED}, - - {"Pm1bEventBlock", - ACPI_FADT_OFFSET(xpm1b_event_block), - ACPI_FADT_OFFSET(pm1b_event_block), - ACPI_FADT_OFFSET(pm1_event_length), - ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ - 0}, - - {"Pm1aControlBlock", - ACPI_FADT_OFFSET(xpm1a_control_block), - ACPI_FADT_OFFSET(pm1a_control_block), - ACPI_FADT_OFFSET(pm1_control_length), - ACPI_PM1_REGISTER_WIDTH, - ACPI_FADT_REQUIRED}, - - {"Pm1bControlBlock", - ACPI_FADT_OFFSET(xpm1b_control_block), - ACPI_FADT_OFFSET(pm1b_control_block), - ACPI_FADT_OFFSET(pm1_control_length), - ACPI_PM1_REGISTER_WIDTH, - 0}, - - {"Pm2ControlBlock", - ACPI_FADT_OFFSET(xpm2_control_block), - ACPI_FADT_OFFSET(pm2_control_block), - ACPI_FADT_OFFSET(pm2_control_length), - ACPI_PM2_REGISTER_WIDTH, - ACPI_FADT_SEPARATE_LENGTH}, - - {"PmTimerBlock", - ACPI_FADT_OFFSET(xpm_timer_block), - ACPI_FADT_OFFSET(pm_timer_block), - ACPI_FADT_OFFSET(pm_timer_length), - ACPI_PM_TIMER_WIDTH, - ACPI_FADT_REQUIRED}, - - {"Gpe0Block", - ACPI_FADT_OFFSET(xgpe0_block), - ACPI_FADT_OFFSET(gpe0_block), - ACPI_FADT_OFFSET(gpe0_block_length), - 0, - ACPI_FADT_SEPARATE_LENGTH}, - - {"Gpe1Block", - ACPI_FADT_OFFSET(xgpe1_block), - ACPI_FADT_OFFSET(gpe1_block), - ACPI_FADT_OFFSET(gpe1_block_length), - 0, - ACPI_FADT_SEPARATE_LENGTH} -}; - -#define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) - -/******************************************************************************* - * - * FUNCTION: acpi_tb_init_generic_address - * - * PARAMETERS: generic_address - GAS struct to be initialized - * byte_width - Width of this register - * Address - Address of the register - * - * RETURN: None - * - * DESCRIPTION: Initialize a Generic Address Structure (GAS) - * See the ACPI specification for a full description and - * definition of this structure. - * - ******************************************************************************/ - -static inline void -acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 space_id, u8 byte_width, u64 address) -{ - - /* - * The 64-bit Address field is non-aligned in the byte packed - * GAS struct. - */ - ACPI_MOVE_64_TO_64(&generic_address->address, &address); - - /* All other fields are byte-wide */ - - generic_address->space_id = space_id; - generic_address->bit_width = (u8)ACPI_MUL_8(byte_width); - generic_address->bit_offset = 0; - generic_address->access_width = 0; /* Access width ANY */ -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_parse_fadt - * - * PARAMETERS: table_index - Index for the FADT - * Flags - Flags - * - * RETURN: None - * - * DESCRIPTION: Initialize the FADT, DSDT and FACS tables - * (FADT contains the addresses of the DSDT and FACS) - * - ******************************************************************************/ - -void acpi_tb_parse_fadt(u32 table_index, u8 flags) -{ - u32 length; - struct acpi_table_header *table; - - /* - * The FADT has multiple versions with different lengths, - * and it contains pointers to both the DSDT and FACS tables. - * - * Get a local copy of the FADT and convert it to a common format - * Map entire FADT, assumed to be smaller than one page. - */ - length = acpi_gbl_root_table_list.tables[table_index].length; - - table = - acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index]. - address, length); - if (!table) { - return; - } - - /* - * Validate the FADT checksum before we copy the table. Ignore - * checksum error as we want to try to get the DSDT and FACS. - */ - (void)acpi_tb_verify_checksum(table, length); - - /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ - - acpi_tb_create_local_fadt(table, length); - - /* All done with the real FADT, unmap it */ - - acpi_os_unmap_memory(table, length); - - /* Obtain the DSDT and FACS tables via their addresses within the FADT */ - - acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, - flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); - - acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, - flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_create_local_fadt - * - * PARAMETERS: Table - Pointer to BIOS FADT - * Length - Length of the table - * - * RETURN: None - * - * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. - * Performs validation on some important FADT fields. - * - * NOTE: We create a local copy of the FADT regardless of the version. - * - ******************************************************************************/ - -void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) -{ - - /* - * Check if the FADT is larger than the largest table that we expect - * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue - * a warning. - */ - if (length > sizeof(struct acpi_table_fadt)) { - ACPI_WARNING((AE_INFO, - "FADT (revision %u) is longer than ACPI 2.0 version, " - "truncating length 0x%X to 0x%zX", - table->revision, (unsigned)length, - sizeof(struct acpi_table_fadt))); - } - - /* Clear the entire local FADT */ - - ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); - - /* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */ - - ACPI_MEMCPY(&acpi_gbl_FADT, table, - ACPI_MIN(length, sizeof(struct acpi_table_fadt))); - - /* - * 1) Convert the local copy of the FADT to the common internal format - * 2) Validate some of the important values within the FADT - */ - acpi_tb_convert_fadt(); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_convert_fadt - * - * PARAMETERS: None, uses acpi_gbl_FADT - * - * RETURN: None - * - * DESCRIPTION: Converts all versions of the FADT to a common internal format. - * Expand all 32-bit addresses to 64-bit. - * - * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), - * and must contain a copy of the actual FADT. - * - * ACPICA will use the "X" fields of the FADT for all addresses. - * - * "X" fields are optional extensions to the original V1.0 fields. Even if - * they are present in the structure, they can be optionally not used by - * setting them to zero. Therefore, we must selectively expand V1.0 fields - * if the corresponding X field is zero. - * - * For ACPI 1.0 FADTs, all address fields are expanded to the corresponding - * "X" fields. - * - * For ACPI 2.0 FADTs, any "X" fields that are NULL are filled in by - * expanding the corresponding ACPI 1.0 field. - * - ******************************************************************************/ - -static void acpi_tb_convert_fadt(void) -{ - u8 pm1_register_bit_width; - u8 pm1_register_byte_width; - struct acpi_generic_address *target64; - u32 i; - - /* Update the local FADT table header length */ - - acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); - - /* - * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. - * Later code will always use the X 64-bit field. Also, check for an - * address mismatch between the 32-bit and 64-bit address fields - * (FIRMWARE_CTRL/X_FIRMWARE_CTRL, DSDT/X_DSDT) which would indicate - * the presence of two FACS or two DSDT tables. - */ - if (!acpi_gbl_FADT.Xfacs) { - acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; - } else if (acpi_gbl_FADT.facs && - (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) { - ACPI_WARNING((AE_INFO, - "32/64 FACS address mismatch in FADT - two FACS tables!")); - } - - if (!acpi_gbl_FADT.Xdsdt) { - acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; - } else if (acpi_gbl_FADT.dsdt && - (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) { - ACPI_WARNING((AE_INFO, - "32/64 DSDT address mismatch in FADT - two DSDT tables!")); - } - - /* - * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which - * should be zero are indeed zero. This will workaround BIOSs that - * inadvertently place values in these fields. - * - * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at - * offset 45, 55, 95, and the word located at offset 109, 110. - */ - if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) { - acpi_gbl_FADT.preferred_profile = 0; - acpi_gbl_FADT.pstate_control = 0; - acpi_gbl_FADT.cst_control = 0; - acpi_gbl_FADT.boot_flags = 0; - } - - /* - * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" - * generic address structures as necessary. Later code will always use - * the 64-bit address structures. - */ - for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { - target64 = - ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, - fadt_info_table[i].address64); - - /* Expand only if the 64-bit X target is null */ - - if (!target64->address) { - - /* The space_id is always I/O for the 32-bit legacy address fields */ - - acpi_tb_init_generic_address(target64, - ACPI_ADR_SPACE_SYSTEM_IO, - *ACPI_ADD_PTR(u8, - &acpi_gbl_FADT, - fadt_info_table - [i].length), - (u64) * ACPI_ADD_PTR(u32, - &acpi_gbl_FADT, - fadt_info_table - [i]. - address32)); - } - } - - /* Validate FADT values now, before we make any changes */ - - acpi_tb_validate_fadt(); - - /* - * Optionally check all register lengths against the default values and - * update them if they are incorrect. - */ - if (acpi_gbl_use_default_register_widths) { - for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { - target64 = - ACPI_ADD_PTR(struct acpi_generic_address, - &acpi_gbl_FADT, - fadt_info_table[i].address64); - - /* - * If a valid register (Address != 0) and the (default_length > 0) - * (Not a GPE register), then check the width against the default. - */ - if ((target64->address) && - (fadt_info_table[i].default_length > 0) && - (fadt_info_table[i].default_length != - target64->bit_width)) { - ACPI_WARNING((AE_INFO, - "Invalid length for %s: %d, using default %d", - fadt_info_table[i].name, - target64->bit_width, - fadt_info_table[i]. - default_length)); - - /* Incorrect size, set width to the default */ - - target64->bit_width = - fadt_info_table[i].default_length; - } - } - } - - /* - * Get the length of the individual PM1 registers (enable and status). - * Each register is defined to be (event block length / 2). - */ - pm1_register_bit_width = - (u8)ACPI_DIV_2(acpi_gbl_FADT.xpm1a_event_block.bit_width); - pm1_register_byte_width = (u8)ACPI_DIV_8(pm1_register_bit_width); - - /* - * Adjust the lengths of the PM1 Event Blocks so that they can be used to - * access the PM1 status register(s). Use (width / 2) - */ - acpi_gbl_FADT.xpm1a_event_block.bit_width = pm1_register_bit_width; - acpi_gbl_FADT.xpm1b_event_block.bit_width = pm1_register_bit_width; - - /* - * Calculate separate GAS structs for the PM1 Enable registers. - * These addresses do not appear (directly) in the FADT, so it is - * useful to calculate them once, here. - * - * The PM event blocks are split into two register blocks, first is the - * PM Status Register block, followed immediately by the PM Enable - * Register block. Each is of length (xpm1x_event_block.bit_width/2). - * - * On various systems the v2 fields (and particularly the bit widths) - * cannot be relied upon, though. Hence resort to using the v1 length - * here (and warn about the inconsistency). - */ - if (acpi_gbl_FADT.xpm1a_event_block.bit_width - != acpi_gbl_FADT.pm1_event_length * 8) - printk(KERN_WARNING "FADT: " - "X_PM1a_EVT_BLK.bit_width (%u) does not match" - " PM1_EVT_LEN (%u)\n", - acpi_gbl_FADT.xpm1a_event_block.bit_width, - acpi_gbl_FADT.pm1_event_length); - - /* The PM1A register block is required */ - - acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, - acpi_gbl_FADT.xpm1a_event_block.space_id, - pm1_register_byte_width, - (acpi_gbl_FADT.xpm1a_event_block.address + - pm1_register_byte_width)); - /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1a_enable.space_id = - acpi_gbl_FADT.xpm1a_event_block.space_id; - - /* The PM1B register block is optional, ignore if not present */ - - if (acpi_gbl_FADT.xpm1b_event_block.address) { - if (acpi_gbl_FADT.xpm1b_event_block.bit_width - != acpi_gbl_FADT.pm1_event_length * 8) - printk(KERN_WARNING "FADT: " - "X_PM1b_EVT_BLK.bit_width (%u) does not match" - " PM1_EVT_LEN (%u)\n", - acpi_gbl_FADT.xpm1b_event_block.bit_width, - acpi_gbl_FADT.pm1_event_length); - acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, - acpi_gbl_FADT.xpm1b_event_block.space_id, - pm1_register_byte_width, - (acpi_gbl_FADT.xpm1b_event_block. - address + pm1_register_byte_width)); - /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1b_enable.space_id = - acpi_gbl_FADT.xpm1b_event_block.space_id; - - } -} - -/****************************************************************************** - * - * FUNCTION: acpi_tb_validate_fadt - * - * PARAMETERS: Table - Pointer to the FADT to be validated - * - * RETURN: None - * - * DESCRIPTION: Validate various important fields within the FADT. If a problem - * is found, issue a message, but no status is returned. - * Used by both the table manager and the disassembler. - * - * Possible additional checks: - * (acpi_gbl_FADT.pm1_event_length >= 4) - * (acpi_gbl_FADT.pm1_control_length >= 2) - * (acpi_gbl_FADT.pm_timer_length >= 4) - * Gpe block lengths must be multiple of 2 - * - ******************************************************************************/ - -static void acpi_tb_validate_fadt(void) -{ - char *name; - u32 *address32; - struct acpi_generic_address *address64; - u8 length; - u32 i; - - /* - * Check for FACS and DSDT address mismatches. An address mismatch between - * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and - * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables. - */ - if (acpi_gbl_FADT.facs && - (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) { - ACPI_WARNING((AE_INFO, - "32/64X FACS address mismatch in FADT - " - "two FACS tables! %8.8X/%8.8X%8.8X", - acpi_gbl_FADT.facs, - ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs))); - } - - if (acpi_gbl_FADT.dsdt && - (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) { - ACPI_WARNING((AE_INFO, - "32/64X DSDT address mismatch in FADT - " - "two DSDT tables! %8.8X/%8.8X%8.8X", - acpi_gbl_FADT.dsdt, - ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt))); - } - - /* Examine all of the 64-bit extended address fields (X fields) */ - - for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { - /* - * Generate pointers to the 32-bit and 64-bit addresses, get the - * register length (width), and the register name - */ - address64 = ACPI_ADD_PTR(struct acpi_generic_address, - &acpi_gbl_FADT, - fadt_info_table[i].address64); - address32 = - ACPI_ADD_PTR(u32, &acpi_gbl_FADT, - fadt_info_table[i].address32); - length = - *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, - fadt_info_table[i].length); - name = fadt_info_table[i].name; - - /* - * For each extended field, check for length mismatch between the - * legacy length field and the corresponding 64-bit X length field. - */ - if (address64 && (address64->bit_width != ACPI_MUL_8(length))) { - ACPI_WARNING((AE_INFO, - "32/64X length mismatch in %s: %d/%d", - name, ACPI_MUL_8(length), - address64->bit_width)); - } - - if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) { - /* - * Field is required (Pm1a_event, Pm1a_control, pm_timer). - * Both the address and length must be non-zero. - */ - if (!address64->address || !length) { - ACPI_ERROR((AE_INFO, - "Required field %s has zero address and/or length: %8.8X%8.8X/%X", - name, - ACPI_FORMAT_UINT64(address64-> - address), - length)); - } - } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { - /* - * Field is optional (PM2Control, GPE0, GPE1) AND has its own - * length field. If present, both the address and length must be valid. - */ - if ((address64->address && !length) - || (!address64->address && length)) { - ACPI_WARNING((AE_INFO, - "Optional field %s has zero address or length: %8.8X%8.8X/%X", - name, - ACPI_FORMAT_UINT64(address64-> - address), - length)); - } - } - - /* If both 32- and 64-bit addresses are valid (non-zero), they must match */ - - if (address64->address && *address32 && - (address64->address != (u64) * address32)) { - ACPI_ERROR((AE_INFO, - "32/64X address mismatch in %s: %8.8X/%8.8X%8.8X, using 64X", - name, *address32, - ACPI_FORMAT_UINT64(address64->address))); - } - } -} diff --git a/drivers/acpi/tables/tbfind.c b/drivers/acpi/tables/tbfind.c deleted file mode 100644 index 9d20cb6db892..000000000000 --- a/drivers/acpi/tables/tbfind.c +++ /dev/null @@ -1,140 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbfind - find table - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_TABLES -ACPI_MODULE_NAME("tbfind") - -/******************************************************************************* - * - * FUNCTION: acpi_tb_find_table - * - * PARAMETERS: Signature - String with ACPI table signature - * oem_id - String with the table OEM ID - * oem_table_id - String with the OEM Table ID - * table_index - Where the table index is returned - * - * RETURN: Status and table index - * - * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the - * Signature, OEM ID and OEM Table ID. Returns an index that can - * be used to get the table header or entire table. - * - ******************************************************************************/ -acpi_status -acpi_tb_find_table(char *signature, - char *oem_id, char *oem_table_id, u32 *table_index) -{ - u32 i; - acpi_status status; - struct acpi_table_header header; - - ACPI_FUNCTION_TRACE(tb_find_table); - - /* Normalize the input strings */ - - ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header)); - ACPI_STRNCPY(header.signature, signature, ACPI_NAME_SIZE); - ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE); - ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE); - - /* Search for the table */ - - for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { - if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature), - header.signature, ACPI_NAME_SIZE)) { - - /* Not the requested table */ - - continue; - } - - /* Table with matching signature has been found */ - - if (!acpi_gbl_root_table_list.tables[i].pointer) { - - /* Table is not currently mapped, map it */ - - status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[i]); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (!acpi_gbl_root_table_list.tables[i].pointer) { - continue; - } - } - - /* Check for table match on all IDs */ - - if (!ACPI_MEMCMP - (acpi_gbl_root_table_list.tables[i].pointer->signature, - header.signature, ACPI_NAME_SIZE) && (!oem_id[0] - || - !ACPI_MEMCMP - (acpi_gbl_root_table_list. - tables[i].pointer-> - oem_id, - header.oem_id, - ACPI_OEM_ID_SIZE)) - && (!oem_table_id[0] - || !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i]. - pointer->oem_table_id, - header.oem_table_id, - ACPI_OEM_TABLE_ID_SIZE))) { - *table_index = i; - - ACPI_DEBUG_PRINT((ACPI_DB_TABLES, - "Found table [%4.4s]\n", - header.signature)); - return_ACPI_STATUS(AE_OK); - } - } - - return_ACPI_STATUS(AE_NOT_FOUND); -} diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c deleted file mode 100644 index 019b0d84cbea..000000000000 --- a/drivers/acpi/tables/tbinstal.c +++ /dev/null @@ -1,574 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbinstal - ACPI table installation and removal - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_TABLES -ACPI_MODULE_NAME("tbinstal") - -/****************************************************************************** - * - * FUNCTION: acpi_tb_verify_table - * - * PARAMETERS: table_desc - table - * - * RETURN: Status - * - * DESCRIPTION: this function is called to verify and map table - * - *****************************************************************************/ -acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(tb_verify_table); - - /* Map the table if necessary */ - - if (!table_desc->pointer) { - if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == - ACPI_TABLE_ORIGIN_MAPPED) { - table_desc->pointer = - acpi_os_map_memory(table_desc->address, - table_desc->length); - } - if (!table_desc->pointer) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - } - - /* FACS is the odd table, has no standard ACPI header and no checksum */ - - if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) { - - /* Always calculate checksum, ignore bad checksum if requested */ - - status = - acpi_tb_verify_checksum(table_desc->pointer, - table_desc->length); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_add_table - * - * PARAMETERS: table_desc - Table descriptor - * table_index - Where the table index is returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to add the ACPI table - * - ******************************************************************************/ - -acpi_status -acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) -{ - u32 i; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(tb_add_table); - - if (!table_desc->pointer) { - status = acpi_tb_verify_table(table_desc); - if (ACPI_FAILURE(status) || !table_desc->pointer) { - return_ACPI_STATUS(status); - } - } - - /* - * Originally, we checked the table signature for "SSDT" or "PSDT" here. - * Next, we added support for OEMx tables, signature "OEM". - * Valid tables were encountered with a null signature, so we've just - * given up on validating the signature, since it seems to be a waste - * of code. The original code was removed (05/2008). - */ - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - - /* Check if table is already registered */ - - for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { - if (!acpi_gbl_root_table_list.tables[i].pointer) { - status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[i]); - if (ACPI_FAILURE(status) - || !acpi_gbl_root_table_list.tables[i].pointer) { - continue; - } - } - - /* - * Check for a table match on the entire table length, - * not just the header. - */ - if (table_desc->length != - acpi_gbl_root_table_list.tables[i].length) { - continue; - } - - if (ACPI_MEMCMP(table_desc->pointer, - acpi_gbl_root_table_list.tables[i].pointer, - acpi_gbl_root_table_list.tables[i].length)) { - continue; - } - - /* - * Note: the current mechanism does not unregister a table if it is - * dynamically unloaded. The related namespace entries are deleted, - * but the table remains in the root table list. - * - * The assumption here is that the number of different tables that - * will be loaded is actually small, and there is minimal overhead - * in just keeping the table in case it is needed again. - * - * If this assumption changes in the future (perhaps on large - * machines with many table load/unload operations), tables will - * need to be unregistered when they are unloaded, and slots in the - * root table list should be reused when empty. - */ - - /* - * Table is already registered. - * We can delete the table that was passed as a parameter. - */ - acpi_tb_delete_table(table_desc); - *table_index = i; - - if (acpi_gbl_root_table_list.tables[i]. - flags & ACPI_TABLE_IS_LOADED) { - - /* Table is still loaded, this is an error */ - - status = AE_ALREADY_EXISTS; - goto release; - } else { - /* Table was unloaded, allow it to be reloaded */ - - table_desc->pointer = - acpi_gbl_root_table_list.tables[i].pointer; - table_desc->address = - acpi_gbl_root_table_list.tables[i].address; - status = AE_OK; - goto print_header; - } - } - - /* Add the table to the global root table list */ - - status = acpi_tb_store_table(table_desc->address, table_desc->pointer, - table_desc->length, table_desc->flags, - table_index); - if (ACPI_FAILURE(status)) { - goto release; - } - - print_header: - acpi_tb_print_table_header(table_desc->address, table_desc->pointer); - - release: - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_resize_root_table_list - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Expand the size of global table array - * - ******************************************************************************/ - -acpi_status acpi_tb_resize_root_table_list(void) -{ - struct acpi_table_desc *tables; - - ACPI_FUNCTION_TRACE(tb_resize_root_table_list); - - /* allow_resize flag is a parameter to acpi_initialize_tables */ - - if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { - ACPI_ERROR((AE_INFO, - "Resize of Root Table Array is not allowed")); - return_ACPI_STATUS(AE_SUPPORT); - } - - /* Increase the Table Array size */ - - tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list. - size + ACPI_ROOT_TABLE_SIZE_INCREMENT) - * sizeof(struct acpi_table_desc)); - if (!tables) { - ACPI_ERROR((AE_INFO, - "Could not allocate new root table array")); - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Copy and free the previous table array */ - - if (acpi_gbl_root_table_list.tables) { - ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, - (acpi_size) acpi_gbl_root_table_list.size * - sizeof(struct acpi_table_desc)); - - if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { - ACPI_FREE(acpi_gbl_root_table_list.tables); - } - } - - acpi_gbl_root_table_list.tables = tables; - acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT; - acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED; - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_store_table - * - * PARAMETERS: Address - Table address - * Table - Table header - * Length - Table length - * Flags - flags - * - * RETURN: Status and table index. - * - * DESCRIPTION: Add an ACPI table to the global table list - * - ******************************************************************************/ - -acpi_status -acpi_tb_store_table(acpi_physical_address address, - struct acpi_table_header *table, - u32 length, u8 flags, u32 *table_index) -{ - acpi_status status = AE_OK; - - /* Ensure that there is room for the table in the Root Table List */ - - if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) { - status = acpi_tb_resize_root_table_list(); - if (ACPI_FAILURE(status)) { - return (status); - } - } - - /* Initialize added table */ - - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. - address = address; - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. - pointer = table; - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length = - length; - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. - owner_id = 0; - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags = - flags; - - ACPI_MOVE_32_TO_32(& - (acpi_gbl_root_table_list. - tables[acpi_gbl_root_table_list.count].signature), - table->signature); - - *table_index = acpi_gbl_root_table_list.count; - acpi_gbl_root_table_list.count++; - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_delete_table - * - * PARAMETERS: table_index - Table index - * - * RETURN: None - * - * DESCRIPTION: Delete one internal ACPI table - * - ******************************************************************************/ - -void acpi_tb_delete_table(struct acpi_table_desc *table_desc) -{ - /* Table must be mapped or allocated */ - if (!table_desc->pointer) { - return; - } - switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { - case ACPI_TABLE_ORIGIN_MAPPED: - acpi_os_unmap_memory(table_desc->pointer, table_desc->length); - break; - case ACPI_TABLE_ORIGIN_ALLOCATED: - ACPI_FREE(table_desc->pointer); - break; - default:; - } - - table_desc->pointer = NULL; -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_terminate - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Delete all internal ACPI tables - * - ******************************************************************************/ - -void acpi_tb_terminate(void) -{ - u32 i; - - ACPI_FUNCTION_TRACE(tb_terminate); - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - - /* Delete the individual tables */ - - for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { - acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]); - } - - /* - * Delete the root table array if allocated locally. Array cannot be - * mapped, so we don't need to check for that flag. - */ - if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { - ACPI_FREE(acpi_gbl_root_table_list.tables); - } - - acpi_gbl_root_table_list.tables = NULL; - acpi_gbl_root_table_list.flags = 0; - acpi_gbl_root_table_list.count = 0; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_delete_namespace_by_owner - * - * PARAMETERS: table_index - Table index - * - * RETURN: None - * - * DESCRIPTION: Delete all namespace objects created when this table was loaded. - * - ******************************************************************************/ - -void acpi_tb_delete_namespace_by_owner(u32 table_index) -{ - acpi_owner_id owner_id; - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - owner_id = - acpi_gbl_root_table_list.tables[table_index].owner_id; - } else { - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return; - } - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - acpi_ns_delete_namespace_by_owner(owner_id); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_allocate_owner_id - * - * PARAMETERS: table_index - Table index - * - * RETURN: Status - * - * DESCRIPTION: Allocates owner_id in table_desc - * - ******************************************************************************/ - -acpi_status acpi_tb_allocate_owner_id(u32 table_index) -{ - acpi_status status = AE_BAD_PARAMETER; - - ACPI_FUNCTION_TRACE(tb_allocate_owner_id); - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - status = acpi_ut_allocate_owner_id - (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); - } - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_release_owner_id - * - * PARAMETERS: table_index - Table index - * - * RETURN: Status - * - * DESCRIPTION: Releases owner_id in table_desc - * - ******************************************************************************/ - -acpi_status acpi_tb_release_owner_id(u32 table_index) -{ - acpi_status status = AE_BAD_PARAMETER; - - ACPI_FUNCTION_TRACE(tb_release_owner_id); - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - acpi_ut_release_owner_id(& - (acpi_gbl_root_table_list. - tables[table_index].owner_id)); - status = AE_OK; - } - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_owner_id - * - * PARAMETERS: table_index - Table index - * owner_id - Where the table owner_id is returned - * - * RETURN: Status - * - * DESCRIPTION: returns owner_id for the ACPI table - * - ******************************************************************************/ - -acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id) -{ - acpi_status status = AE_BAD_PARAMETER; - - ACPI_FUNCTION_TRACE(tb_get_owner_id); - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - *owner_id = - acpi_gbl_root_table_list.tables[table_index].owner_id; - status = AE_OK; - } - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_is_table_loaded - * - * PARAMETERS: table_index - Table index - * - * RETURN: Table Loaded Flag - * - ******************************************************************************/ - -u8 acpi_tb_is_table_loaded(u32 table_index) -{ - u8 is_loaded = FALSE; - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - is_loaded = (u8) - (acpi_gbl_root_table_list.tables[table_index]. - flags & ACPI_TABLE_IS_LOADED); - } - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return (is_loaded); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_set_table_loaded_flag - * - * PARAMETERS: table_index - Table index - * is_loaded - TRUE if table is loaded, FALSE otherwise - * - * RETURN: None - * - * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. - * - ******************************************************************************/ - -void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded) -{ - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - if (is_loaded) { - acpi_gbl_root_table_list.tables[table_index].flags |= - ACPI_TABLE_IS_LOADED; - } else { - acpi_gbl_root_table_list.tables[table_index].flags &= - ~ACPI_TABLE_IS_LOADED; - } - } - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); -} diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c deleted file mode 100644 index 4eb7189974ca..000000000000 --- a/drivers/acpi/tables/tbutils.c +++ /dev/null @@ -1,582 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbutils - table utilities - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_TABLES -ACPI_MODULE_NAME("tbutils") - -/* Local prototypes */ -static acpi_physical_address -acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); - -/******************************************************************************* - * - * FUNCTION: acpi_tb_check_xsdt - * - * PARAMETERS: address - Pointer to the XSDT - * - * RETURN: status - * AE_OK - XSDT is okay - * AE_NO_MEMORY - can't map XSDT - * AE_INVALID_TABLE_LENGTH - invalid table length - * AE_NULL_ENTRY - XSDT has NULL entry - * - * DESCRIPTION: validate XSDT -******************************************************************************/ - -static acpi_status -acpi_tb_check_xsdt(acpi_physical_address address) -{ - struct acpi_table_header *table; - u32 length; - u64 xsdt_entry_address; - u8 *table_entry; - u32 table_count; - int i; - - table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); - if (!table) - return AE_NO_MEMORY; - - length = table->length; - acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); - if (length < sizeof(struct acpi_table_header)) - return AE_INVALID_TABLE_LENGTH; - - table = acpi_os_map_memory(address, length); - if (!table) - return AE_NO_MEMORY; - - /* Calculate the number of tables described in XSDT */ - table_count = - (u32) ((table->length - - sizeof(struct acpi_table_header)) / sizeof(u64)); - table_entry = - ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); - for (i = 0; i < table_count; i++) { - ACPI_MOVE_64_TO_64(&xsdt_entry_address, table_entry); - if (!xsdt_entry_address) { - /* XSDT has NULL entry */ - break; - } - table_entry += sizeof(u64); - } - acpi_os_unmap_memory(table, length); - - if (i < table_count) - return AE_NULL_ENTRY; - else - return AE_OK; -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_initialize_facs - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global - * for accessing the Global Lock and Firmware Waking Vector - * - ******************************************************************************/ - -acpi_status acpi_tb_initialize_facs(void) -{ - acpi_status status; - - status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, - ACPI_CAST_INDIRECT_PTR(struct - acpi_table_header, - &acpi_gbl_FACS)); - return status; -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_tables_loaded - * - * PARAMETERS: None - * - * RETURN: TRUE if required ACPI tables are loaded - * - * DESCRIPTION: Determine if the minimum required ACPI tables are present - * (FADT, FACS, DSDT) - * - ******************************************************************************/ - -u8 acpi_tb_tables_loaded(void) -{ - - if (acpi_gbl_root_table_list.count >= 3) { - return (TRUE); - } - - return (FALSE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_print_table_header - * - * PARAMETERS: Address - Table physical address - * Header - Table header - * - * RETURN: None - * - * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. - * - ******************************************************************************/ - -void -acpi_tb_print_table_header(acpi_physical_address address, - struct acpi_table_header *header) -{ - - if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { - - /* FACS only has signature and length fields of common table header */ - - ACPI_INFO((AE_INFO, "%4.4s %08lX, %04X", - header->signature, (unsigned long)address, - header->length)); - } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { - - /* RSDP has no common fields */ - - ACPI_INFO((AE_INFO, "RSDP %08lX, %04X (r%d %6.6s)", - (unsigned long)address, - (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> - revision > - 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->length : 20, - ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->revision, - ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->oem_id)); - } else { - /* Standard ACPI table with full common header */ - - ACPI_INFO((AE_INFO, - "%4.4s %08lX, %04X (r%d %6.6s %8.8s %8X %4.4s %8X)", - header->signature, (unsigned long)address, - header->length, header->revision, header->oem_id, - header->oem_table_id, header->oem_revision, - header->asl_compiler_id, - header->asl_compiler_revision)); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_validate_checksum - * - * PARAMETERS: Table - ACPI table to verify - * Length - Length of entire table - * - * RETURN: Status - * - * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns - * exception on bad checksum. - * - ******************************************************************************/ - -acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) -{ - u8 checksum; - - /* Compute the checksum on the table */ - - checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); - - /* Checksum ok? (should be zero) */ - - if (checksum) { - ACPI_WARNING((AE_INFO, - "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", - table->signature, table->checksum, - (u8) (table->checksum - checksum))); - -#if (ACPI_CHECKSUM_ABORT) - - return (AE_BAD_CHECKSUM); -#endif - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_checksum - * - * PARAMETERS: Buffer - Pointer to memory region to be checked - * Length - Length of this memory region - * - * RETURN: Checksum (u8) - * - * DESCRIPTION: Calculates circular checksum of memory region. - * - ******************************************************************************/ - -u8 acpi_tb_checksum(u8 *buffer, u32 length) -{ - u8 sum = 0; - u8 *end = buffer + length; - - while (buffer < end) { - sum = (u8) (sum + *(buffer++)); - } - - return sum; -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_install_table - * - * PARAMETERS: Address - Physical address of DSDT or FACS - * Flags - Flags - * Signature - Table signature, NULL if no need to - * match - * table_index - Index into root table array - * - * RETURN: None - * - * DESCRIPTION: Install an ACPI table into the global data structure. - * - ******************************************************************************/ - -void -acpi_tb_install_table(acpi_physical_address address, - u8 flags, char *signature, u32 table_index) -{ - struct acpi_table_header *table; - - if (!address) { - ACPI_ERROR((AE_INFO, - "Null physical address for ACPI table [%s]", - signature)); - return; - } - - /* Map just the table header */ - - table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); - if (!table) { - return; - } - - /* If a particular signature is expected, signature must match */ - - if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { - ACPI_ERROR((AE_INFO, - "Invalid signature 0x%X for ACPI table [%s]", - *ACPI_CAST_PTR(u32, table->signature), signature)); - goto unmap_and_exit; - } - - /* Initialize the table entry */ - - acpi_gbl_root_table_list.tables[table_index].address = address; - acpi_gbl_root_table_list.tables[table_index].length = table->length; - acpi_gbl_root_table_list.tables[table_index].flags = flags; - - ACPI_MOVE_32_TO_32(& - (acpi_gbl_root_table_list.tables[table_index]. - signature), table->signature); - - acpi_tb_print_table_header(address, table); - - if (table_index == ACPI_TABLE_INDEX_DSDT) { - - /* Global integer width is based upon revision of the DSDT */ - - acpi_ut_set_integer_width(table->revision); - } - - unmap_and_exit: - acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_root_table_entry - * - * PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry - * table_entry_size - sizeof 32 or 64 (RSDT or XSDT) - * - * RETURN: Physical address extracted from the root table - * - * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on - * both 32-bit and 64-bit platforms - * - * NOTE: acpi_physical_address is 32-bit on 32-bit platforms, 64-bit on - * 64-bit platforms. - * - ******************************************************************************/ - -static acpi_physical_address -acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) -{ - u64 address64; - - /* - * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): - * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT - */ - if (table_entry_size == sizeof(u32)) { - /* - * 32-bit platform, RSDT: Return 32-bit table entry - * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return - */ - return ((acpi_physical_address) - (*ACPI_CAST_PTR(u32, table_entry))); - } else { - /* - * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return - * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit - */ - ACPI_MOVE_64_TO_64(&address64, table_entry); - -#if ACPI_MACHINE_WIDTH == 32 - if (address64 > ACPI_UINT32_MAX) { - - /* Will truncate 64-bit address to 32 bits, issue warning */ - - ACPI_WARNING((AE_INFO, - "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating", - ACPI_FORMAT_UINT64(address64))); - } -#endif - return ((acpi_physical_address) (address64)); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_parse_root_table - * - * PARAMETERS: Rsdp - Pointer to the RSDP - * Flags - Flags - * - * RETURN: Status - * - * DESCRIPTION: This function is called to parse the Root System Description - * Table (RSDT or XSDT) - * - * NOTE: Tables are mapped (not copied) for efficiency. The FACS must - * be mapped and cannot be copied because it contains the actual - * memory location of the ACPI Global Lock. - * - ******************************************************************************/ - -acpi_status __init -acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) -{ - struct acpi_table_rsdp *rsdp; - u32 table_entry_size; - u32 i; - u32 table_count; - struct acpi_table_header *table; - acpi_physical_address address; - acpi_physical_address uninitialized_var(rsdt_address); - u32 length; - u8 *table_entry; - acpi_status status; - - ACPI_FUNCTION_TRACE(tb_parse_root_table); - - /* - * Map the entire RSDP and extract the address of the RSDT or XSDT - */ - rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp)); - if (!rsdp) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - acpi_tb_print_table_header(rsdp_address, - ACPI_CAST_PTR(struct acpi_table_header, - rsdp)); - - /* Differentiate between RSDT and XSDT root tables */ - - if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { - /* - * Root table is an XSDT (64-bit physical addresses). We must use the - * XSDT if the revision is > 1 and the XSDT pointer is present, as per - * the ACPI specification. - */ - address = (acpi_physical_address) rsdp->xsdt_physical_address; - table_entry_size = sizeof(u64); - rsdt_address = (acpi_physical_address) - rsdp->rsdt_physical_address; - } else { - /* Root table is an RSDT (32-bit physical addresses) */ - - address = (acpi_physical_address) rsdp->rsdt_physical_address; - table_entry_size = sizeof(u32); - } - - /* - * It is not possible to map more than one entry in some environments, - * so unmap the RSDP here before mapping other tables - */ - acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); - - if (table_entry_size == sizeof(u64)) { - if (acpi_tb_check_xsdt(address) == AE_NULL_ENTRY) { - /* XSDT has NULL entry, RSDT is used */ - address = rsdt_address; - table_entry_size = sizeof(u32); - ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry, " - "using RSDT")); - } - } - /* Map the RSDT/XSDT table header to get the full table length */ - - table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); - if (!table) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - acpi_tb_print_table_header(address, table); - - /* Get the length of the full table, verify length and map entire table */ - - length = table->length; - acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); - - if (length < sizeof(struct acpi_table_header)) { - ACPI_ERROR((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", - length)); - return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); - } - - table = acpi_os_map_memory(address, length); - if (!table) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Validate the root table checksum */ - - status = acpi_tb_verify_checksum(table, length); - if (ACPI_FAILURE(status)) { - acpi_os_unmap_memory(table, length); - return_ACPI_STATUS(status); - } - - /* Calculate the number of tables described in the root table */ - - table_count = - (u32) ((table->length - - sizeof(struct acpi_table_header)) / table_entry_size); - - /* - * First two entries in the table array are reserved for the DSDT and FACS, - * which are not actually present in the RSDT/XSDT - they come from the FADT - */ - table_entry = - ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); - acpi_gbl_root_table_list.count = 2; - - /* - * Initialize the root table array from the RSDT/XSDT - */ - for (i = 0; i < table_count; i++) { - if (acpi_gbl_root_table_list.count >= - acpi_gbl_root_table_list.size) { - - /* There is no more room in the root table array, attempt resize */ - - status = acpi_tb_resize_root_table_list(); - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, - "Truncating %u table entries!", - (unsigned) - (acpi_gbl_root_table_list.size - - acpi_gbl_root_table_list. - count))); - break; - } - } - - /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ - - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. - address = - acpi_tb_get_root_table_entry(table_entry, table_entry_size); - - table_entry += table_entry_size; - acpi_gbl_root_table_list.count++; - } - - /* - * It is not possible to map more than one entry in some environments, - * so unmap the root table here before mapping other tables - */ - acpi_os_unmap_memory(table, length); - - /* - * Complete the initialization of the root table array by examining - * the header of each table - */ - for (i = 2; i < acpi_gbl_root_table_list.count; i++) { - acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. - address, flags, NULL, i); - - /* Special case for FADT - get the DSDT and FACS */ - - if (ACPI_COMPARE_NAME - (&acpi_gbl_root_table_list.tables[i].signature, - ACPI_SIG_FADT)) { - acpi_tb_parse_fadt(i, flags); - } - } - - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c deleted file mode 100644 index 115796694a2f..000000000000 --- a/drivers/acpi/tables/tbxface.c +++ /dev/null @@ -1,735 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbxface - Public interfaces to the ACPI subsystem - * ACPI table oriented interfaces - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_TABLES -ACPI_MODULE_NAME("tbxface") - -/* Local prototypes */ -static acpi_status acpi_tb_load_namespace(void); - -static int no_auto_ssdt; - -/******************************************************************************* - * - * FUNCTION: acpi_allocate_root_table - * - * PARAMETERS: initial_table_count - Size of initial_table_array, in number of - * struct acpi_table_desc structures - * - * RETURN: Status - * - * DESCRIPTION: Allocate a root table array. Used by i_aSL compiler and - * acpi_initialize_tables. - * - ******************************************************************************/ - -acpi_status acpi_allocate_root_table(u32 initial_table_count) -{ - - acpi_gbl_root_table_list.size = initial_table_count; - acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE; - - return (acpi_tb_resize_root_table_list()); -} - -/******************************************************************************* - * - * FUNCTION: acpi_initialize_tables - * - * PARAMETERS: initial_table_array - Pointer to an array of pre-allocated - * struct acpi_table_desc structures. If NULL, the - * array is dynamically allocated. - * initial_table_count - Size of initial_table_array, in number of - * struct acpi_table_desc structures - * allow_realloc - Flag to tell Table Manager if resize of - * pre-allocated array is allowed. Ignored - * if initial_table_array is NULL. - * - * RETURN: Status - * - * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT. - * - * NOTE: Allows static allocation of the initial table array in order - * to avoid the use of dynamic memory in confined environments - * such as the kernel boot sequence where it may not be available. - * - * If the host OS memory managers are initialized, use NULL for - * initial_table_array, and the table will be dynamically allocated. - * - ******************************************************************************/ - -acpi_status __init -acpi_initialize_tables(struct acpi_table_desc * initial_table_array, - u32 initial_table_count, u8 allow_resize) -{ - acpi_physical_address rsdp_address; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_initialize_tables); - - /* - * Set up the Root Table Array - * Allocate the table array if requested - */ - if (!initial_table_array) { - status = acpi_allocate_root_table(initial_table_count); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } else { - /* Root Table Array has been statically allocated by the host */ - - ACPI_MEMSET(initial_table_array, 0, - (acpi_size) initial_table_count * - sizeof(struct acpi_table_desc)); - - acpi_gbl_root_table_list.tables = initial_table_array; - acpi_gbl_root_table_list.size = initial_table_count; - acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN; - if (allow_resize) { - acpi_gbl_root_table_list.flags |= - ACPI_ROOT_ALLOW_RESIZE; - } - } - - /* Get the address of the RSDP */ - - rsdp_address = acpi_os_get_root_pointer(); - if (!rsdp_address) { - return_ACPI_STATUS(AE_NOT_FOUND); - } - - /* - * Get the root table (RSDT or XSDT) and extract all entries to the local - * Root Table Array. This array contains the information of the RSDT/XSDT - * in a common, more useable format. - */ - status = - acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_reallocate_root_table - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the - * root list from the previously provided scratch area. Should - * be called once dynamic memory allocation is available in the - * kernel - * - ******************************************************************************/ -acpi_status acpi_reallocate_root_table(void) -{ - struct acpi_table_desc *tables; - acpi_size new_size; - - ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); - - /* - * Only reallocate the root table if the host provided a static buffer - * for the table array in the call to acpi_initialize_tables. - */ - if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { - return_ACPI_STATUS(AE_SUPPORT); - } - - new_size = ((acpi_size) acpi_gbl_root_table_list.count + - ACPI_ROOT_TABLE_SIZE_INCREMENT) * - sizeof(struct acpi_table_desc); - - /* Create new array and copy the old array */ - - tables = ACPI_ALLOCATE_ZEROED(new_size); - if (!tables) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size); - - acpi_gbl_root_table_list.size = acpi_gbl_root_table_list.count; - acpi_gbl_root_table_list.tables = tables; - acpi_gbl_root_table_list.flags = - ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_load_table - * - * PARAMETERS: table_ptr - pointer to a buffer containing the entire - * table to be loaded - * - * RETURN: Status - * - * DESCRIPTION: This function is called to load a table from the caller's - * buffer. The buffer must contain an entire ACPI Table including - * a valid header. The header fields will be verified, and if it - * is determined that the table is invalid, the call will fail. - * - ******************************************************************************/ -acpi_status acpi_load_table(struct acpi_table_header *table_ptr) -{ - acpi_status status; - u32 table_index; - struct acpi_table_desc table_desc; - - if (!table_ptr) - return AE_BAD_PARAMETER; - - ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); - table_desc.pointer = table_ptr; - table_desc.length = table_ptr->length; - table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN; - - /* - * Install the new table into the local data structures - */ - status = acpi_tb_add_table(&table_desc, &table_index); - if (ACPI_FAILURE(status)) { - return status; - } - status = acpi_ns_load_table(table_index, acpi_gbl_root_node); - return status; -} - -ACPI_EXPORT_SYMBOL(acpi_load_table) - -/****************************************************************************** - * - * FUNCTION: acpi_get_table_header - * - * PARAMETERS: Signature - ACPI signature of needed table - * Instance - Which instance (for SSDTs) - * out_table_header - The pointer to the table header to fill - * - * RETURN: Status and pointer to mapped table header - * - * DESCRIPTION: Finds an ACPI table header. - * - * NOTE: Caller is responsible in unmapping the header with - * acpi_os_unmap_memory - * - *****************************************************************************/ -acpi_status -acpi_get_table_header(char *signature, - u32 instance, struct acpi_table_header *out_table_header) -{ - u32 i; - u32 j; - struct acpi_table_header *header; - - /* Parameter validation */ - - if (!signature || !out_table_header) { - return (AE_BAD_PARAMETER); - } - - /* - * Walk the root table list - */ - for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { - if (!ACPI_COMPARE_NAME - (&(acpi_gbl_root_table_list.tables[i].signature), - signature)) { - continue; - } - - if (++j < instance) { - continue; - } - - if (!acpi_gbl_root_table_list.tables[i].pointer) { - if ((acpi_gbl_root_table_list.tables[i]. - flags & ACPI_TABLE_ORIGIN_MASK) == - ACPI_TABLE_ORIGIN_MAPPED) { - header = - acpi_os_map_memory(acpi_gbl_root_table_list. - tables[i].address, - sizeof(struct - acpi_table_header)); - if (!header) { - return AE_NO_MEMORY; - } - ACPI_MEMCPY(out_table_header, header, - sizeof(struct acpi_table_header)); - acpi_os_unmap_memory(header, - sizeof(struct - acpi_table_header)); - } else { - return AE_NOT_FOUND; - } - } else { - ACPI_MEMCPY(out_table_header, - acpi_gbl_root_table_list.tables[i].pointer, - sizeof(struct acpi_table_header)); - } - return (AE_OK); - } - - return (AE_NOT_FOUND); -} - -ACPI_EXPORT_SYMBOL(acpi_get_table_header) - -/****************************************************************************** - * - * FUNCTION: acpi_unload_table_id - * - * PARAMETERS: id - Owner ID of the table to be removed. - * - * RETURN: Status - * - * DESCRIPTION: This routine is used to force the unload of a table (by id) - * - ******************************************************************************/ -acpi_status acpi_unload_table_id(acpi_owner_id id) -{ - int i; - acpi_status status = AE_NOT_EXIST; - - ACPI_FUNCTION_TRACE(acpi_unload_table_id); - - /* Find table in the global table list */ - for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { - if (id != acpi_gbl_root_table_list.tables[i].owner_id) { - continue; - } - /* - * Delete all namespace objects owned by this table. Note that these - * objects can appear anywhere in the namespace by virtue of the AML - * "Scope" operator. Thus, we need to track ownership by an ID, not - * simply a position within the hierarchy - */ - acpi_tb_delete_namespace_by_owner(i); - status = acpi_tb_release_owner_id(i); - acpi_tb_set_table_loaded_flag(i, FALSE); - break; - } - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_unload_table_id) - -/******************************************************************************* - * - * FUNCTION: acpi_get_table - * - * PARAMETERS: Signature - ACPI signature of needed table - * Instance - Which instance (for SSDTs) - * out_table - Where the pointer to the table is returned - * - * RETURN: Status and pointer to table - * - * DESCRIPTION: Finds and verifies an ACPI table. - * - *****************************************************************************/ -acpi_status -acpi_get_table(char *signature, - u32 instance, struct acpi_table_header **out_table) -{ - u32 i; - u32 j; - acpi_status status; - - /* Parameter validation */ - - if (!signature || !out_table) { - return (AE_BAD_PARAMETER); - } - - /* - * Walk the root table list - */ - for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { - if (!ACPI_COMPARE_NAME - (&(acpi_gbl_root_table_list.tables[i].signature), - signature)) { - continue; - } - - if (++j < instance) { - continue; - } - - status = - acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]); - if (ACPI_SUCCESS(status)) { - *out_table = acpi_gbl_root_table_list.tables[i].pointer; - } - - if (!acpi_gbl_permanent_mmap) { - acpi_gbl_root_table_list.tables[i].pointer = NULL; - } - - return (status); - } - - return (AE_NOT_FOUND); -} - -ACPI_EXPORT_SYMBOL(acpi_get_table) - -/******************************************************************************* - * - * FUNCTION: acpi_get_table_by_index - * - * PARAMETERS: table_index - Table index - * Table - Where the pointer to the table is returned - * - * RETURN: Status and pointer to the table - * - * DESCRIPTION: Obtain a table by an index into the global table list. - * - ******************************************************************************/ -acpi_status -acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_get_table_by_index); - - /* Parameter validation */ - - if (!table) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - - /* Validate index */ - - if (table_index >= acpi_gbl_root_table_list.count) { - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (!acpi_gbl_root_table_list.tables[table_index].pointer) { - - /* Table is not mapped, map it */ - - status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[table_index]); - if (ACPI_FAILURE(status)) { - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); - } - } - - *table = acpi_gbl_root_table_list.tables[table_index].pointer; - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) - -/******************************************************************************* - * - * FUNCTION: acpi_tb_load_namespace - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in - * the RSDT/XSDT. - * - ******************************************************************************/ -static acpi_status acpi_tb_load_namespace(void) -{ - acpi_status status; - struct acpi_table_header *table; - u32 i; - - ACPI_FUNCTION_TRACE(tb_load_namespace); - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - - /* - * Load the namespace. The DSDT is required, but any SSDT and PSDT tables - * are optional. - */ - if (!acpi_gbl_root_table_list.count || - !ACPI_COMPARE_NAME(& - (acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT].signature), - ACPI_SIG_DSDT) - || - ACPI_FAILURE(acpi_tb_verify_table - (&acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT]))) { - status = AE_NO_ACPI_TABLES; - goto unlock_and_exit; - } - - /* - * Find DSDT table - */ - status = - acpi_os_table_override(acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT].pointer, - &table); - if (ACPI_SUCCESS(status) && table) { - /* - * DSDT table has been found - */ - acpi_tb_delete_table(&acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT]); - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer = - table; - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = - table->length; - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = - ACPI_TABLE_ORIGIN_UNKNOWN; - - ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); - acpi_tb_print_table_header(0, table); - - if (no_auto_ssdt == 0) { - printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n"); - } - } - - status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT]); - if (ACPI_FAILURE(status)) { - - /* A valid DSDT is required */ - - status = AE_NO_ACPI_TABLES; - goto unlock_and_exit; - } - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - - /* - * Load and parse tables. - */ - status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Load any SSDT or PSDT tables. Note: Loop leaves tables locked - */ - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { - if ((!ACPI_COMPARE_NAME - (&(acpi_gbl_root_table_list.tables[i].signature), - ACPI_SIG_SSDT) - && - !ACPI_COMPARE_NAME(& - (acpi_gbl_root_table_list.tables[i]. - signature), ACPI_SIG_PSDT)) - || - ACPI_FAILURE(acpi_tb_verify_table - (&acpi_gbl_root_table_list.tables[i]))) { - continue; - } - - if (no_auto_ssdt) { - printk(KERN_WARNING "ACPI: SSDT ignored due to \"acpi_no_auto_ssdt\"\n"); - continue; - } - - /* Ignore errors while loading tables, get as many as possible */ - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - (void)acpi_ns_load_table(i, acpi_gbl_root_node); - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_load_tables - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT - * - ******************************************************************************/ - -acpi_status acpi_load_tables(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_load_tables); - - /* - * Load the namespace from the tables - */ - status = acpi_tb_load_namespace(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "While loading namespace from ACPI tables")); - } - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_load_tables) - - -/******************************************************************************* - * - * FUNCTION: acpi_install_table_handler - * - * PARAMETERS: Handler - Table event handler - * Context - Value passed to the handler on each event - * - * RETURN: Status - * - * DESCRIPTION: Install table event handler - * - ******************************************************************************/ -acpi_status -acpi_install_table_handler(acpi_tbl_handler handler, void *context) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_install_table_handler); - - if (!handler) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Don't allow more than one handler */ - - if (acpi_gbl_table_handler) { - status = AE_ALREADY_EXISTS; - goto cleanup; - } - - /* Install the handler */ - - acpi_gbl_table_handler = handler; - acpi_gbl_table_handler_context = context; - - cleanup: - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_install_table_handler) - -/******************************************************************************* - * - * FUNCTION: acpi_remove_table_handler - * - * PARAMETERS: Handler - Table event handler that was installed - * previously. - * - * RETURN: Status - * - * DESCRIPTION: Remove table event handler - * - ******************************************************************************/ -acpi_status acpi_remove_table_handler(acpi_tbl_handler handler) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_remove_table_handler); - - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Make sure that the installed handler is the same */ - - if (!handler || handler != acpi_gbl_table_handler) { - status = AE_BAD_PARAMETER; - goto cleanup; - } - - /* Remove the handler */ - - acpi_gbl_table_handler = NULL; - - cleanup: - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_remove_table_handler) - - -static int __init acpi_no_auto_ssdt_setup(char *s) { - - printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); - - no_auto_ssdt = 1; - - return 1; -} - -__setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup); diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c deleted file mode 100644 index 3495dca4e86b..000000000000 --- a/drivers/acpi/tables/tbxfroot.c +++ /dev/null @@ -1,274 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbxfroot - Find the root ACPI table (RSDT) - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_TABLES -ACPI_MODULE_NAME("tbxfroot") - -/* Local prototypes */ -static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); - -static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp); - -/******************************************************************************* - * - * FUNCTION: acpi_tb_validate_rsdp - * - * PARAMETERS: Rsdp - Pointer to unvalidated RSDP - * - * RETURN: Status - * - * DESCRIPTION: Validate the RSDP (ptr) - * - ******************************************************************************/ - -static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) -{ - ACPI_FUNCTION_ENTRY(); - - /* - * The signature and checksum must both be correct - * - * Note: Sometimes there exists more than one RSDP in memory; the valid - * RSDP has a valid checksum, all others have an invalid checksum. - */ - if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1) - != 0) { - - /* Nope, BAD Signature */ - - return (AE_BAD_SIGNATURE); - } - - /* Check the standard checksum */ - - if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { - return (AE_BAD_CHECKSUM); - } - - /* Check extended checksum if table version >= 2 */ - - if ((rsdp->revision >= 2) && - (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { - return (AE_BAD_CHECKSUM); - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_find_root_pointer - * - * PARAMETERS: table_address - Where the table pointer is returned - * - * RETURN: Status, RSDP physical address - * - * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor - * pointer structure. If it is found, set *RSDP to point to it. - * - * NOTE1: The RSDP must be either in the first 1_k of the Extended - * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) - * Only a 32-bit physical address is necessary. - * - * NOTE2: This function is always available, regardless of the - * initialization state of the rest of ACPI. - * - ******************************************************************************/ - -acpi_status acpi_find_root_pointer(acpi_size *table_address) -{ - u8 *table_ptr; - u8 *mem_rover; - u32 physical_address; - - ACPI_FUNCTION_TRACE(acpi_find_root_pointer); - - /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ - - table_ptr = acpi_os_map_memory((acpi_physical_address) - ACPI_EBDA_PTR_LOCATION, - ACPI_EBDA_PTR_LENGTH); - if (!table_ptr) { - ACPI_ERROR((AE_INFO, - "Could not map memory at %8.8X for length %X", - ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); - - return_ACPI_STATUS(AE_NO_MEMORY); - } - - ACPI_MOVE_16_TO_32(&physical_address, table_ptr); - - /* Convert segment part to physical address */ - - physical_address <<= 4; - acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH); - - /* EBDA present? */ - - if (physical_address > 0x400) { - /* - * 1b) Search EBDA paragraphs (EBDA is required to be a - * minimum of 1_k length) - */ - table_ptr = acpi_os_map_memory((acpi_physical_address) - physical_address, - ACPI_EBDA_WINDOW_SIZE); - if (!table_ptr) { - ACPI_ERROR((AE_INFO, - "Could not map memory at %8.8X for length %X", - physical_address, ACPI_EBDA_WINDOW_SIZE)); - - return_ACPI_STATUS(AE_NO_MEMORY); - } - - mem_rover = - acpi_tb_scan_memory_for_rsdp(table_ptr, - ACPI_EBDA_WINDOW_SIZE); - acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); - - if (mem_rover) { - - /* Return the physical address */ - - physical_address += - (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); - - *table_address = physical_address; - return_ACPI_STATUS(AE_OK); - } - } - - /* - * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh - */ - table_ptr = acpi_os_map_memory((acpi_physical_address) - ACPI_HI_RSDP_WINDOW_BASE, - ACPI_HI_RSDP_WINDOW_SIZE); - - if (!table_ptr) { - ACPI_ERROR((AE_INFO, - "Could not map memory at %8.8X for length %X", - ACPI_HI_RSDP_WINDOW_BASE, - ACPI_HI_RSDP_WINDOW_SIZE)); - - return_ACPI_STATUS(AE_NO_MEMORY); - } - - mem_rover = - acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); - acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); - - if (mem_rover) { - - /* Return the physical address */ - - physical_address = (u32) - (ACPI_HI_RSDP_WINDOW_BASE + - ACPI_PTR_DIFF(mem_rover, table_ptr)); - - *table_address = physical_address; - return_ACPI_STATUS(AE_OK); - } - - /* A valid RSDP was not found */ - - ACPI_ERROR((AE_INFO, "A valid RSDP was not found")); - return_ACPI_STATUS(AE_NOT_FOUND); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_scan_memory_for_rsdp - * - * PARAMETERS: start_address - Starting pointer for search - * Length - Maximum length to search - * - * RETURN: Pointer to the RSDP if found, otherwise NULL. - * - * DESCRIPTION: Search a block of memory for the RSDP signature - * - ******************************************************************************/ -static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) -{ - acpi_status status; - u8 *mem_rover; - u8 *end_address; - - ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp); - - end_address = start_address + length; - - /* Search from given start address for the requested length */ - - for (mem_rover = start_address; mem_rover < end_address; - mem_rover += ACPI_RSDP_SCAN_STEP) { - - /* The RSDP signature and checksum must both be correct */ - - status = - acpi_tb_validate_rsdp(ACPI_CAST_PTR - (struct acpi_table_rsdp, mem_rover)); - if (ACPI_SUCCESS(status)) { - - /* Sig and checksum valid, we have found a real RSDP */ - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "RSDP located at physical address %p\n", - mem_rover)); - return_PTR(mem_rover); - } - - /* No sig match or bad checksum, keep searching */ - } - - /* Searched entire block, no RSDP was found */ - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Searched entire block from %p, valid RSDP was not found\n", - start_address)); - return_PTR(NULL); -} diff --git a/drivers/acpi/utilities/Makefile b/drivers/acpi/utilities/Makefile deleted file mode 100644 index 66a71a54cb0d..000000000000 --- a/drivers/acpi/utilities/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -obj-y := utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ - utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ - utstate.o utmutex.o utobject.o utresrc.o - -EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c deleted file mode 100644 index 2a017b29aa41..000000000000 --- a/drivers/acpi/utilities/utalloc.c +++ /dev/null @@ -1,383 +0,0 @@ -/****************************************************************************** - * - * Module Name: utalloc - local memory allocation routines - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utalloc") - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_caches - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Create all local caches - * - ******************************************************************************/ -acpi_status acpi_ut_create_caches(void) -{ - acpi_status status; - - /* Object Caches, for frequently used objects */ - - status = - acpi_os_create_cache("Acpi-Namespace", - sizeof(struct acpi_namespace_node), - ACPI_MAX_NAMESPACE_CACHE_DEPTH, - &acpi_gbl_namespace_cache); - if (ACPI_FAILURE(status)) { - return (status); - } - - status = - acpi_os_create_cache("Acpi-State", sizeof(union acpi_generic_state), - ACPI_MAX_STATE_CACHE_DEPTH, - &acpi_gbl_state_cache); - if (ACPI_FAILURE(status)) { - return (status); - } - - status = - acpi_os_create_cache("Acpi-Parse", - sizeof(struct acpi_parse_obj_common), - ACPI_MAX_PARSE_CACHE_DEPTH, - &acpi_gbl_ps_node_cache); - if (ACPI_FAILURE(status)) { - return (status); - } - - status = - acpi_os_create_cache("Acpi-ParseExt", - sizeof(struct acpi_parse_obj_named), - ACPI_MAX_EXTPARSE_CACHE_DEPTH, - &acpi_gbl_ps_node_ext_cache); - if (ACPI_FAILURE(status)) { - return (status); - } - - status = - acpi_os_create_cache("Acpi-Operand", - sizeof(union acpi_operand_object), - ACPI_MAX_OBJECT_CACHE_DEPTH, - &acpi_gbl_operand_cache); - if (ACPI_FAILURE(status)) { - return (status); - } -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - - /* Memory allocation lists */ - - status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list); - if (ACPI_FAILURE(status)) { - return (status); - } - - status = - acpi_ut_create_list("Acpi-Namespace", - sizeof(struct acpi_namespace_node), - &acpi_gbl_ns_node_list); - if (ACPI_FAILURE(status)) { - return (status); - } -#endif - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_delete_caches - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Purge and delete all local caches - * - ******************************************************************************/ - -acpi_status acpi_ut_delete_caches(void) -{ -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - char buffer[7]; - - if (acpi_gbl_display_final_mem_stats) { - ACPI_STRCPY(buffer, "MEMORY"); - (void)acpi_db_display_statistics(buffer); - } -#endif - - (void)acpi_os_delete_cache(acpi_gbl_namespace_cache); - acpi_gbl_namespace_cache = NULL; - - (void)acpi_os_delete_cache(acpi_gbl_state_cache); - acpi_gbl_state_cache = NULL; - - (void)acpi_os_delete_cache(acpi_gbl_operand_cache); - acpi_gbl_operand_cache = NULL; - - (void)acpi_os_delete_cache(acpi_gbl_ps_node_cache); - acpi_gbl_ps_node_cache = NULL; - - (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache); - acpi_gbl_ps_node_ext_cache = NULL; - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - - /* Debug only - display leftover memory allocation, if any */ - - acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL); - - /* Free memory lists */ - - ACPI_FREE(acpi_gbl_global_list); - acpi_gbl_global_list = NULL; - - ACPI_FREE(acpi_gbl_ns_node_list); - acpi_gbl_ns_node_list = NULL; -#endif - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_validate_buffer - * - * PARAMETERS: Buffer - Buffer descriptor to be validated - * - * RETURN: Status - * - * DESCRIPTION: Perform parameter validation checks on an struct acpi_buffer - * - ******************************************************************************/ - -acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer) -{ - - /* Obviously, the structure pointer must be valid */ - - if (!buffer) { - return (AE_BAD_PARAMETER); - } - - /* Special semantics for the length */ - - if ((buffer->length == ACPI_NO_BUFFER) || - (buffer->length == ACPI_ALLOCATE_BUFFER) || - (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) { - return (AE_OK); - } - - /* Length is valid, the buffer pointer must be also */ - - if (!buffer->pointer) { - return (AE_BAD_PARAMETER); - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_initialize_buffer - * - * PARAMETERS: Buffer - Buffer to be validated - * required_length - Length needed - * - * RETURN: Status - * - * DESCRIPTION: Validate that the buffer is of the required length or - * allocate a new buffer. Returned buffer is always zeroed. - * - ******************************************************************************/ - -acpi_status -acpi_ut_initialize_buffer(struct acpi_buffer * buffer, - acpi_size required_length) -{ - acpi_size input_buffer_length; - - /* Parameter validation */ - - if (!buffer || !required_length) { - return (AE_BAD_PARAMETER); - } - - /* - * Buffer->Length is used as both an input and output parameter. Get the - * input actual length and set the output required buffer length. - */ - input_buffer_length = buffer->length; - buffer->length = required_length; - - /* - * The input buffer length contains the actual buffer length, or the type - * of buffer to be allocated by this routine. - */ - switch (input_buffer_length) { - case ACPI_NO_BUFFER: - - /* Return the exception (and the required buffer length) */ - - return (AE_BUFFER_OVERFLOW); - - case ACPI_ALLOCATE_BUFFER: - - /* Allocate a new buffer */ - - buffer->pointer = acpi_os_allocate(required_length); - break; - - case ACPI_ALLOCATE_LOCAL_BUFFER: - - /* Allocate a new buffer with local interface to allow tracking */ - - buffer->pointer = ACPI_ALLOCATE(required_length); - break; - - default: - - /* Existing buffer: Validate the size of the buffer */ - - if (input_buffer_length < required_length) { - return (AE_BUFFER_OVERFLOW); - } - break; - } - - /* Validate allocation from above or input buffer pointer */ - - if (!buffer->pointer) { - return (AE_NO_MEMORY); - } - - /* Have a valid buffer, clear it */ - - ACPI_MEMSET(buffer->pointer, 0, required_length); - return (AE_OK); -} - -#ifdef NOT_USED_BY_LINUX -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate - * - * PARAMETERS: Size - Size of the allocation - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: Subsystem equivalent of malloc. - * - ******************************************************************************/ - -void *acpi_ut_allocate(acpi_size size, - u32 component, const char *module, u32 line) -{ - void *allocation; - - ACPI_FUNCTION_TRACE_U32(ut_allocate, size); - - /* Check for an inadvertent size of zero bytes */ - - if (!size) { - ACPI_WARNING((module, line, - "Attempt to allocate zero bytes, allocating 1 byte")); - size = 1; - } - - allocation = acpi_os_allocate(size); - if (!allocation) { - - /* Report allocation error */ - - ACPI_WARNING((module, line, - "Could not allocate size %X", (u32) size)); - - return_PTR(NULL); - } - - return_PTR(allocation); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate_zeroed - * - * PARAMETERS: Size - Size of the allocation - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. - * - ******************************************************************************/ - -void *acpi_ut_allocate_zeroed(acpi_size size, - u32 component, const char *module, u32 line) -{ - void *allocation; - - ACPI_FUNCTION_ENTRY(); - - allocation = acpi_ut_allocate(size, component, module, line); - if (allocation) { - - /* Clear the memory block */ - - ACPI_MEMSET(allocation, 0, size); - } - - return (allocation); -} -#endif diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c deleted file mode 100644 index e6f3002312e5..000000000000 --- a/drivers/acpi/utilities/utcopy.c +++ /dev/null @@ -1,970 +0,0 @@ -/****************************************************************************** - * - * Module Name: utcopy - Internal to external object translation utilities - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utcopy") - -/* Local prototypes */ -static acpi_status -acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, - union acpi_object *external_object, - u8 * data_space, acpi_size * buffer_space_used); - -static acpi_status -acpi_ut_copy_ielement_to_ielement(u8 object_type, - union acpi_operand_object *source_object, - union acpi_generic_state *state, - void *context); - -static acpi_status -acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object, - u8 * buffer, acpi_size * space_used); - -static acpi_status -acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj, - union acpi_operand_object **return_obj); - -static acpi_status -acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, - union acpi_operand_object **internal_object); - -static acpi_status -acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, - union acpi_operand_object *dest_desc); - -static acpi_status -acpi_ut_copy_ielement_to_eelement(u8 object_type, - union acpi_operand_object *source_object, - union acpi_generic_state *state, - void *context); - -static acpi_status -acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, - union acpi_operand_object *dest_obj, - struct acpi_walk_state *walk_state); - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_isimple_to_esimple - * - * PARAMETERS: internal_object - Source object to be copied - * external_object - Where to return the copied object - * data_space - Where object data is returned (such as - * buffer and string data) - * buffer_space_used - Length of data_space that was used - * - * RETURN: Status - * - * DESCRIPTION: This function is called to copy a simple internal object to - * an external object. - * - * The data_space buffer is assumed to have sufficient space for - * the object. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, - union acpi_object *external_object, - u8 * data_space, acpi_size * buffer_space_used) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple); - - *buffer_space_used = 0; - - /* - * Check for NULL object case (could be an uninitialized - * package element) - */ - if (!internal_object) { - return_ACPI_STATUS(AE_OK); - } - - /* Always clear the external object */ - - ACPI_MEMSET(external_object, 0, sizeof(union acpi_object)); - - /* - * In general, the external object will be the same type as - * the internal object - */ - external_object->type = ACPI_GET_OBJECT_TYPE(internal_object); - - /* However, only a limited number of external types are supported */ - - switch (ACPI_GET_OBJECT_TYPE(internal_object)) { - case ACPI_TYPE_STRING: - - external_object->string.pointer = (char *)data_space; - external_object->string.length = internal_object->string.length; - *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size) - internal_object-> - string. - length + 1); - - ACPI_MEMCPY((void *)data_space, - (void *)internal_object->string.pointer, - (acpi_size) internal_object->string.length + 1); - break; - - case ACPI_TYPE_BUFFER: - - external_object->buffer.pointer = data_space; - external_object->buffer.length = internal_object->buffer.length; - *buffer_space_used = - ACPI_ROUND_UP_TO_NATIVE_WORD(internal_object->string. - length); - - ACPI_MEMCPY((void *)data_space, - (void *)internal_object->buffer.pointer, - internal_object->buffer.length); - break; - - case ACPI_TYPE_INTEGER: - - external_object->integer.value = internal_object->integer.value; - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - - /* This is an object reference. */ - - switch (internal_object->reference.class) { - case ACPI_REFCLASS_NAME: - - /* - * For namepath, return the object handle ("reference") - * We are referring to the namespace node - */ - external_object->reference.handle = - internal_object->reference.node; - external_object->reference.actual_type = - acpi_ns_get_type(internal_object->reference.node); - break; - - default: - - /* All other reference types are unsupported */ - - return_ACPI_STATUS(AE_TYPE); - } - break; - - case ACPI_TYPE_PROCESSOR: - - external_object->processor.proc_id = - internal_object->processor.proc_id; - external_object->processor.pblk_address = - internal_object->processor.address; - external_object->processor.pblk_length = - internal_object->processor.length; - break; - - case ACPI_TYPE_POWER: - - external_object->power_resource.system_level = - internal_object->power_resource.system_level; - - external_object->power_resource.resource_order = - internal_object->power_resource.resource_order; - break; - - default: - /* - * There is no corresponding external object type - */ - ACPI_ERROR((AE_INFO, - "Unsupported object type, cannot convert to external object: %s", - acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE - (internal_object)))); - - return_ACPI_STATUS(AE_SUPPORT); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_ielement_to_eelement - * - * PARAMETERS: acpi_pkg_callback - * - * RETURN: Status - * - * DESCRIPTION: Copy one package element to another package element - * - ******************************************************************************/ - -static acpi_status -acpi_ut_copy_ielement_to_eelement(u8 object_type, - union acpi_operand_object *source_object, - union acpi_generic_state *state, - void *context) -{ - acpi_status status = AE_OK; - struct acpi_pkg_info *info = (struct acpi_pkg_info *)context; - acpi_size object_space; - u32 this_index; - union acpi_object *target_object; - - ACPI_FUNCTION_ENTRY(); - - this_index = state->pkg.index; - target_object = (union acpi_object *) - &((union acpi_object *)(state->pkg.dest_object))->package. - elements[this_index]; - - switch (object_type) { - case ACPI_COPY_TYPE_SIMPLE: - - /* - * This is a simple or null object - */ - status = acpi_ut_copy_isimple_to_esimple(source_object, - target_object, - info->free_space, - &object_space); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_COPY_TYPE_PACKAGE: - - /* - * Build the package object - */ - target_object->type = ACPI_TYPE_PACKAGE; - target_object->package.count = source_object->package.count; - target_object->package.elements = - ACPI_CAST_PTR(union acpi_object, info->free_space); - - /* - * Pass the new package object back to the package walk routine - */ - state->pkg.this_target_obj = target_object; - - /* - * Save space for the array of objects (Package elements) - * update the buffer length counter - */ - object_space = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size) - target_object-> - package.count * - sizeof(union - acpi_object)); - break; - - default: - return (AE_BAD_PARAMETER); - } - - info->free_space += object_space; - info->length += object_space; - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_ipackage_to_epackage - * - * PARAMETERS: internal_object - Pointer to the object we are returning - * Buffer - Where the object is returned - * space_used - Where the object length is returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to place a package object in a user - * buffer. A package object by definition contains other objects. - * - * The buffer is assumed to have sufficient space for the object. - * The caller must have verified the buffer length needed using the - * acpi_ut_get_object_size function before calling this function. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object, - u8 * buffer, acpi_size * space_used) -{ - union acpi_object *external_object; - acpi_status status; - struct acpi_pkg_info info; - - ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage); - - /* - * First package at head of the buffer - */ - external_object = ACPI_CAST_PTR(union acpi_object, buffer); - - /* - * Free space begins right after the first package - */ - info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); - info.free_space = - buffer + ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); - info.object_space = 0; - info.num_packages = 1; - - external_object->type = ACPI_GET_OBJECT_TYPE(internal_object); - external_object->package.count = internal_object->package.count; - external_object->package.elements = ACPI_CAST_PTR(union acpi_object, - info.free_space); - - /* - * Leave room for an array of ACPI_OBJECTS in the buffer - * and move the free space past it - */ - info.length += (acpi_size) external_object->package.count * - ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); - info.free_space += external_object->package.count * - ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); - - status = acpi_ut_walk_package_tree(internal_object, external_object, - acpi_ut_copy_ielement_to_eelement, - &info); - - *space_used = info.length; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_iobject_to_eobject - * - * PARAMETERS: internal_object - The internal object to be converted - * buffer_ptr - Where the object is returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to build an API object to be returned to - * the caller. - * - ******************************************************************************/ - -acpi_status -acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object, - struct acpi_buffer *ret_buffer) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject); - - if (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE) { - /* - * Package object: Copy all subobjects (including - * nested packages) - */ - status = acpi_ut_copy_ipackage_to_epackage(internal_object, - ret_buffer->pointer, - &ret_buffer->length); - } else { - /* - * Build a simple object (no nested objects) - */ - status = acpi_ut_copy_isimple_to_esimple(internal_object, - ACPI_CAST_PTR(union - acpi_object, - ret_buffer-> - pointer), - ACPI_ADD_PTR(u8, - ret_buffer-> - pointer, - ACPI_ROUND_UP_TO_NATIVE_WORD - (sizeof - (union - acpi_object))), - &ret_buffer->length); - /* - * build simple does not include the object size in the length - * so we add it in here - */ - ret_buffer->length += sizeof(union acpi_object); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_esimple_to_isimple - * - * PARAMETERS: external_object - The external object to be converted - * ret_internal_object - Where the internal object is returned - * - * RETURN: Status - * - * DESCRIPTION: This function copies an external object to an internal one. - * NOTE: Pointers can be copied, we don't need to copy data. - * (The pointers have to be valid in our address space no matter - * what we do with them!) - * - ******************************************************************************/ - -static acpi_status -acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, - union acpi_operand_object **ret_internal_object) -{ - union acpi_operand_object *internal_object; - - ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple); - - /* - * Simple types supported are: String, Buffer, Integer - */ - switch (external_object->type) { - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_LOCAL_REFERENCE: - - internal_object = acpi_ut_create_internal_object((u8) - external_object-> - type); - if (!internal_object) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - break; - - case ACPI_TYPE_ANY: /* This is the case for a NULL object */ - - *ret_internal_object = NULL; - return_ACPI_STATUS(AE_OK); - - default: - /* All other types are not supported */ - - ACPI_ERROR((AE_INFO, - "Unsupported object type, cannot convert to internal object: %s", - acpi_ut_get_type_name(external_object->type))); - - return_ACPI_STATUS(AE_SUPPORT); - } - - /* Must COPY string and buffer contents */ - - switch (external_object->type) { - case ACPI_TYPE_STRING: - - internal_object->string.pointer = - ACPI_ALLOCATE_ZEROED((acpi_size) external_object->string. - length + 1); - if (!internal_object->string.pointer) { - goto error_exit; - } - - ACPI_MEMCPY(internal_object->string.pointer, - external_object->string.pointer, - external_object->string.length); - - internal_object->string.length = external_object->string.length; - break; - - case ACPI_TYPE_BUFFER: - - internal_object->buffer.pointer = - ACPI_ALLOCATE_ZEROED(external_object->buffer.length); - if (!internal_object->buffer.pointer) { - goto error_exit; - } - - ACPI_MEMCPY(internal_object->buffer.pointer, - external_object->buffer.pointer, - external_object->buffer.length); - - internal_object->buffer.length = external_object->buffer.length; - - /* Mark buffer data valid */ - - internal_object->buffer.flags |= AOPOBJ_DATA_VALID; - break; - - case ACPI_TYPE_INTEGER: - - internal_object->integer.value = external_object->integer.value; - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - - /* TBD: should validate incoming handle */ - - internal_object->reference.class = ACPI_REFCLASS_NAME; - internal_object->reference.node = - external_object->reference.handle; - break; - - default: - /* Other types can't get here */ - break; - } - - *ret_internal_object = internal_object; - return_ACPI_STATUS(AE_OK); - - error_exit: - acpi_ut_remove_reference(internal_object); - return_ACPI_STATUS(AE_NO_MEMORY); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_epackage_to_ipackage - * - * PARAMETERS: external_object - The external object to be converted - * internal_object - Where the internal object is returned - * - * RETURN: Status - * - * DESCRIPTION: Copy an external package object to an internal package. - * Handles nested packages. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, - union acpi_operand_object **internal_object) -{ - acpi_status status = AE_OK; - union acpi_operand_object *package_object; - union acpi_operand_object **package_elements; - u32 i; - - ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage); - - /* Create the package object */ - - package_object = - acpi_ut_create_package_object(external_object->package.count); - if (!package_object) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - package_elements = package_object->package.elements; - - /* - * Recursive implementation. Probably ok, since nested external packages - * as parameters should be very rare. - */ - for (i = 0; i < external_object->package.count; i++) { - status = - acpi_ut_copy_eobject_to_iobject(&external_object->package. - elements[i], - &package_elements[i]); - if (ACPI_FAILURE(status)) { - - /* Truncate package and delete it */ - - package_object->package.count = i; - package_elements[i] = NULL; - acpi_ut_remove_reference(package_object); - return_ACPI_STATUS(status); - } - } - - /* Mark package data valid */ - - package_object->package.flags |= AOPOBJ_DATA_VALID; - - *internal_object = package_object; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_eobject_to_iobject - * - * PARAMETERS: external_object - The external object to be converted - * internal_object - Where the internal object is returned - * - * RETURN: Status - the status of the call - * - * DESCRIPTION: Converts an external object to an internal object. - * - ******************************************************************************/ - -acpi_status -acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object, - union acpi_operand_object **internal_object) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject); - - if (external_object->type == ACPI_TYPE_PACKAGE) { - status = - acpi_ut_copy_epackage_to_ipackage(external_object, - internal_object); - } else { - /* - * Build a simple object (no nested objects) - */ - status = - acpi_ut_copy_esimple_to_isimple(external_object, - internal_object); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_simple_object - * - * PARAMETERS: source_desc - The internal object to be copied - * dest_desc - New target object - * - * RETURN: Status - * - * DESCRIPTION: Simple copy of one internal object to another. Reference count - * of the destination object is preserved. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, - union acpi_operand_object *dest_desc) -{ - u16 reference_count; - union acpi_operand_object *next_object; - - /* Save fields from destination that we don't want to overwrite */ - - reference_count = dest_desc->common.reference_count; - next_object = dest_desc->common.next_object; - - /* Copy the entire source object over the destination object */ - - ACPI_MEMCPY((char *)dest_desc, (char *)source_desc, - sizeof(union acpi_operand_object)); - - /* Restore the saved fields */ - - dest_desc->common.reference_count = reference_count; - dest_desc->common.next_object = next_object; - - /* New object is not static, regardless of source */ - - dest_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; - - /* Handle the objects with extra data */ - - switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { - case ACPI_TYPE_BUFFER: - /* - * Allocate and copy the actual buffer if and only if: - * 1) There is a valid buffer pointer - * 2) The buffer has a length > 0 - */ - if ((source_desc->buffer.pointer) && - (source_desc->buffer.length)) { - dest_desc->buffer.pointer = - ACPI_ALLOCATE(source_desc->buffer.length); - if (!dest_desc->buffer.pointer) { - return (AE_NO_MEMORY); - } - - /* Copy the actual buffer data */ - - ACPI_MEMCPY(dest_desc->buffer.pointer, - source_desc->buffer.pointer, - source_desc->buffer.length); - } - break; - - case ACPI_TYPE_STRING: - /* - * Allocate and copy the actual string if and only if: - * 1) There is a valid string pointer - * (Pointer to a NULL string is allowed) - */ - if (source_desc->string.pointer) { - dest_desc->string.pointer = - ACPI_ALLOCATE((acpi_size) source_desc->string. - length + 1); - if (!dest_desc->string.pointer) { - return (AE_NO_MEMORY); - } - - /* Copy the actual string data */ - - ACPI_MEMCPY(dest_desc->string.pointer, - source_desc->string.pointer, - (acpi_size) source_desc->string.length + 1); - } - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - /* - * We copied the reference object, so we now must add a reference - * to the object pointed to by the reference - * - * DDBHandle reference (from Load/load_table) is a special reference, - * it does not have a Reference.Object, so does not need to - * increase the reference count - */ - if (source_desc->reference.class == ACPI_REFCLASS_TABLE) { - break; - } - - acpi_ut_add_reference(source_desc->reference.object); - break; - - case ACPI_TYPE_REGION: - /* - * We copied the Region Handler, so we now must add a reference - */ - if (dest_desc->region.handler) { - acpi_ut_add_reference(dest_desc->region.handler); - } - break; - - default: - /* Nothing to do for other simple objects */ - break; - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_ielement_to_ielement - * - * PARAMETERS: acpi_pkg_callback - * - * RETURN: Status - * - * DESCRIPTION: Copy one package element to another package element - * - ******************************************************************************/ - -static acpi_status -acpi_ut_copy_ielement_to_ielement(u8 object_type, - union acpi_operand_object *source_object, - union acpi_generic_state *state, - void *context) -{ - acpi_status status = AE_OK; - u32 this_index; - union acpi_operand_object **this_target_ptr; - union acpi_operand_object *target_object; - - ACPI_FUNCTION_ENTRY(); - - this_index = state->pkg.index; - this_target_ptr = (union acpi_operand_object **) - &state->pkg.dest_object->package.elements[this_index]; - - switch (object_type) { - case ACPI_COPY_TYPE_SIMPLE: - - /* A null source object indicates a (legal) null package element */ - - if (source_object) { - /* - * This is a simple object, just copy it - */ - target_object = - acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE - (source_object)); - if (!target_object) { - return (AE_NO_MEMORY); - } - - status = - acpi_ut_copy_simple_object(source_object, - target_object); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - - *this_target_ptr = target_object; - } else { - /* Pass through a null element */ - - *this_target_ptr = NULL; - } - break; - - case ACPI_COPY_TYPE_PACKAGE: - - /* - * This object is a package - go down another nesting level - * Create and build the package object - */ - target_object = - acpi_ut_create_package_object(source_object->package.count); - if (!target_object) { - return (AE_NO_MEMORY); - } - - target_object->common.flags = source_object->common.flags; - - /* Pass the new package object back to the package walk routine */ - - state->pkg.this_target_obj = target_object; - - /* Store the object pointer in the parent package object */ - - *this_target_ptr = target_object; - break; - - default: - return (AE_BAD_PARAMETER); - } - - return (status); - - error_exit: - acpi_ut_remove_reference(target_object); - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_ipackage_to_ipackage - * - * PARAMETERS: *source_obj - Pointer to the source package object - * *dest_obj - Where the internal object is returned - * - * RETURN: Status - the status of the call - * - * DESCRIPTION: This function is called to copy an internal package object - * into another internal package object. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, - union acpi_operand_object *dest_obj, - struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage); - - dest_obj->common.type = ACPI_GET_OBJECT_TYPE(source_obj); - dest_obj->common.flags = source_obj->common.flags; - dest_obj->package.count = source_obj->package.count; - - /* - * Create the object array and walk the source package tree - */ - dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) - source_obj->package. - count + - 1) * sizeof(void *)); - if (!dest_obj->package.elements) { - ACPI_ERROR((AE_INFO, "Package allocation failure")); - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* - * Copy the package element-by-element by walking the package "tree". - * This handles nested packages of arbitrary depth. - */ - status = acpi_ut_walk_package_tree(source_obj, dest_obj, - acpi_ut_copy_ielement_to_ielement, - walk_state); - if (ACPI_FAILURE(status)) { - - /* On failure, delete the destination package object */ - - acpi_ut_remove_reference(dest_obj); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_iobject_to_iobject - * - * PARAMETERS: walk_state - Current walk state - * source_desc - The internal object to be copied - * dest_desc - Where the copied object is returned - * - * RETURN: Status - * - * DESCRIPTION: Copy an internal object to a new internal object - * - ******************************************************************************/ - -acpi_status -acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc, - union acpi_operand_object **dest_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject); - - /* Create the top level object */ - - *dest_desc = - acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE(source_desc)); - if (!*dest_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Copy the object and possible subobjects */ - - if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_PACKAGE) { - status = - acpi_ut_copy_ipackage_to_ipackage(source_desc, *dest_desc, - walk_state); - } else { - status = acpi_ut_copy_simple_object(source_desc, *dest_desc); - } - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c deleted file mode 100644 index 9a3538c497d0..000000000000 --- a/drivers/acpi/utilities/utdebug.c +++ /dev/null @@ -1,651 +0,0 @@ -/****************************************************************************** - * - * Module Name: utdebug - Debug print routines - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utdebug") -#ifdef ACPI_DEBUG_OUTPUT -static acpi_thread_id acpi_gbl_prev_thread_id; -static char *acpi_gbl_fn_entry_str = "----Entry"; -static char *acpi_gbl_fn_exit_str = "----Exit-"; - -/* Local prototypes */ - -static const char *acpi_ut_trim_function_name(const char *function_name); - -/******************************************************************************* - * - * FUNCTION: acpi_ut_init_stack_ptr_trace - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Save the current CPU stack pointer at subsystem startup - * - ******************************************************************************/ - -void acpi_ut_init_stack_ptr_trace(void) -{ - acpi_size current_sp; - - acpi_gbl_entry_stack_pointer = ¤t_sp; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_track_stack_ptr - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Save the current CPU stack pointer - * - ******************************************************************************/ - -void acpi_ut_track_stack_ptr(void) -{ - acpi_size current_sp; - - if (¤t_sp < acpi_gbl_lowest_stack_pointer) { - acpi_gbl_lowest_stack_pointer = ¤t_sp; - } - - if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) { - acpi_gbl_deepest_nesting = acpi_gbl_nesting_level; - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_trim_function_name - * - * PARAMETERS: function_name - Ascii string containing a procedure name - * - * RETURN: Updated pointer to the function name - * - * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present. - * This allows compiler macros such as __func__ to be used - * with no change to the debug output. - * - ******************************************************************************/ - -static const char *acpi_ut_trim_function_name(const char *function_name) -{ - - /* All Function names are longer than 4 chars, check is safe */ - - if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_MIXED) { - - /* This is the case where the original source has not been modified */ - - return (function_name + 4); - } - - if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_LOWER) { - - /* This is the case where the source has been 'linuxized' */ - - return (function_name + 5); - } - - return (function_name); -} - -/******************************************************************************* - * - * FUNCTION: acpi_debug_print - * - * PARAMETERS: requested_debug_level - Requested debug print level - * line_number - Caller's line number (for error output) - * function_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID - * Format - Printf format field - * ... - Optional printf arguments - * - * RETURN: None - * - * DESCRIPTION: Print error message with prefix consisting of the module name, - * line number, and component ID. - * - ******************************************************************************/ - -void ACPI_INTERNAL_VAR_XFACE -acpi_debug_print(u32 requested_debug_level, - u32 line_number, - const char *function_name, - const char *module_name, - u32 component_id, const char *format, ...) -{ - acpi_thread_id thread_id; - va_list args; - - /* - * Stay silent if the debug level or component ID is disabled - */ - if (!(requested_debug_level & acpi_dbg_level) || - !(component_id & acpi_dbg_layer)) { - return; - } - - /* - * Thread tracking and context switch notification - */ - thread_id = acpi_os_get_thread_id(); - if (thread_id != acpi_gbl_prev_thread_id) { - if (ACPI_LV_THREADS & acpi_dbg_level) { - acpi_os_printf - ("\n**** Context Switch from TID %lX to TID %lX ****\n\n", - (unsigned long)acpi_gbl_prev_thread_id, - (unsigned long)thread_id); - } - - acpi_gbl_prev_thread_id = thread_id; - } - - /* - * Display the module name, current line number, thread ID (if requested), - * current procedure nesting level, and the current procedure name - */ - acpi_os_printf("%8s-%04ld ", module_name, line_number); - - if (ACPI_LV_THREADS & acpi_dbg_level) { - acpi_os_printf("[%04lX] ", (unsigned long)thread_id); - } - - acpi_os_printf("[%02ld] %-22.22s: ", - acpi_gbl_nesting_level, - acpi_ut_trim_function_name(function_name)); - - va_start(args, format); - acpi_os_vprintf(format, args); - va_end(args); -} - -ACPI_EXPORT_SYMBOL(acpi_debug_print) - -/******************************************************************************* - * - * FUNCTION: acpi_debug_print_raw - * - * PARAMETERS: requested_debug_level - Requested debug print level - * line_number - Caller's line number - * function_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID - * Format - Printf format field - * ... - Optional printf arguments - * - * RETURN: None - * - * DESCRIPTION: Print message with no headers. Has same interface as - * debug_print so that the same macros can be used. - * - ******************************************************************************/ -void ACPI_INTERNAL_VAR_XFACE -acpi_debug_print_raw(u32 requested_debug_level, - u32 line_number, - const char *function_name, - const char *module_name, - u32 component_id, const char *format, ...) -{ - va_list args; - - if (!(requested_debug_level & acpi_dbg_level) || - !(component_id & acpi_dbg_layer)) { - return; - } - - va_start(args, format); - acpi_os_vprintf(format, args); - va_end(args); -} - -ACPI_EXPORT_SYMBOL(acpi_debug_print_raw) - -/******************************************************************************* - * - * FUNCTION: acpi_ut_trace - * - * PARAMETERS: line_number - Caller's line number - * function_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID - * - * RETURN: None - * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is - * set in debug_level - * - ******************************************************************************/ -void -acpi_ut_trace(u32 line_number, - const char *function_name, - const char *module_name, u32 component_id) -{ - - acpi_gbl_nesting_level++; - acpi_ut_track_stack_ptr(); - - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s\n", acpi_gbl_fn_entry_str); -} - -ACPI_EXPORT_SYMBOL(acpi_ut_trace) - -/******************************************************************************* - * - * FUNCTION: acpi_ut_trace_ptr - * - * PARAMETERS: line_number - Caller's line number - * function_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID - * Pointer - Pointer to display - * - * RETURN: None - * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is - * set in debug_level - * - ******************************************************************************/ -void -acpi_ut_trace_ptr(u32 line_number, - const char *function_name, - const char *module_name, u32 component_id, void *pointer) -{ - acpi_gbl_nesting_level++; - acpi_ut_track_stack_ptr(); - - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %p\n", acpi_gbl_fn_entry_str, pointer); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_trace_str - * - * PARAMETERS: line_number - Caller's line number - * function_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID - * String - Additional string to display - * - * RETURN: None - * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is - * set in debug_level - * - ******************************************************************************/ - -void -acpi_ut_trace_str(u32 line_number, - const char *function_name, - const char *module_name, u32 component_id, char *string) -{ - - acpi_gbl_nesting_level++; - acpi_ut_track_stack_ptr(); - - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %s\n", acpi_gbl_fn_entry_str, string); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_trace_u32 - * - * PARAMETERS: line_number - Caller's line number - * function_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID - * Integer - Integer to display - * - * RETURN: None - * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is - * set in debug_level - * - ******************************************************************************/ - -void -acpi_ut_trace_u32(u32 line_number, - const char *function_name, - const char *module_name, u32 component_id, u32 integer) -{ - - acpi_gbl_nesting_level++; - acpi_ut_track_stack_ptr(); - - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %08X\n", acpi_gbl_fn_entry_str, integer); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_exit - * - * PARAMETERS: line_number - Caller's line number - * function_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID - * - * RETURN: None - * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is - * set in debug_level - * - ******************************************************************************/ - -void -acpi_ut_exit(u32 line_number, - const char *function_name, - const char *module_name, u32 component_id) -{ - - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s\n", acpi_gbl_fn_exit_str); - - acpi_gbl_nesting_level--; -} - -ACPI_EXPORT_SYMBOL(acpi_ut_exit) - -/******************************************************************************* - * - * FUNCTION: acpi_ut_status_exit - * - * PARAMETERS: line_number - Caller's line number - * function_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID - * Status - Exit status code - * - * RETURN: None - * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is - * set in debug_level. Prints exit status also. - * - ******************************************************************************/ -void -acpi_ut_status_exit(u32 line_number, - const char *function_name, - const char *module_name, - u32 component_id, acpi_status status) -{ - - if (ACPI_SUCCESS(status)) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, - component_id, "%s %s\n", acpi_gbl_fn_exit_str, - acpi_format_exception(status)); - } else { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, - component_id, "%s ****Exception****: %s\n", - acpi_gbl_fn_exit_str, - acpi_format_exception(status)); - } - - acpi_gbl_nesting_level--; -} - -ACPI_EXPORT_SYMBOL(acpi_ut_status_exit) - -/******************************************************************************* - * - * FUNCTION: acpi_ut_value_exit - * - * PARAMETERS: line_number - Caller's line number - * function_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID - * Value - Value to be printed with exit msg - * - * RETURN: None - * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is - * set in debug_level. Prints exit value also. - * - ******************************************************************************/ -void -acpi_ut_value_exit(u32 line_number, - const char *function_name, - const char *module_name, - u32 component_id, acpi_integer value) -{ - - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str, - ACPI_FORMAT_UINT64(value)); - - acpi_gbl_nesting_level--; -} - -ACPI_EXPORT_SYMBOL(acpi_ut_value_exit) - -/******************************************************************************* - * - * FUNCTION: acpi_ut_ptr_exit - * - * PARAMETERS: line_number - Caller's line number - * function_name - Caller's procedure name - * module_name - Caller's module name - * component_id - Caller's component ID - * Ptr - Pointer to display - * - * RETURN: None - * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is - * set in debug_level. Prints exit value also. - * - ******************************************************************************/ -void -acpi_ut_ptr_exit(u32 line_number, - const char *function_name, - const char *module_name, u32 component_id, u8 *ptr) -{ - - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %p\n", acpi_gbl_fn_exit_str, ptr); - - acpi_gbl_nesting_level--; -} - -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ut_dump_buffer - * - * PARAMETERS: Buffer - Buffer to dump - * Count - Amount to dump, in bytes - * Display - BYTE, WORD, DWORD, or QWORD display - * component_iD - Caller's component ID - * - * RETURN: None - * - * DESCRIPTION: Generic dump buffer in both hex and ascii. - * - ******************************************************************************/ - -void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) -{ - u32 i = 0; - u32 j; - u32 temp32; - u8 buf_char; - - if (!buffer) { - acpi_os_printf("Null Buffer Pointer in DumpBuffer!\n"); - return; - } - - if ((count < 4) || (count & 0x01)) { - display = DB_BYTE_DISPLAY; - } - - /* Nasty little dump buffer routine! */ - - while (i < count) { - - /* Print current offset */ - - acpi_os_printf("%6.4X: ", i); - - /* Print 16 hex chars */ - - for (j = 0; j < 16;) { - if (i + j >= count) { - - /* Dump fill spaces */ - - acpi_os_printf("%*s", ((display * 2) + 1), " "); - j += display; - continue; - } - - switch (display) { - case DB_BYTE_DISPLAY: - default: /* Default is BYTE display */ - - acpi_os_printf("%02X ", - buffer[(acpi_size) i + j]); - break; - - case DB_WORD_DISPLAY: - - ACPI_MOVE_16_TO_32(&temp32, - &buffer[(acpi_size) i + j]); - acpi_os_printf("%04X ", temp32); - break; - - case DB_DWORD_DISPLAY: - - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j]); - acpi_os_printf("%08X ", temp32); - break; - - case DB_QWORD_DISPLAY: - - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j]); - acpi_os_printf("%08X", temp32); - - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j + - 4]); - acpi_os_printf("%08X ", temp32); - break; - } - - j += display; - } - - /* - * Print the ASCII equivalent characters but watch out for the bad - * unprintable ones (printable chars are 0x20 through 0x7E) - */ - acpi_os_printf(" "); - for (j = 0; j < 16; j++) { - if (i + j >= count) { - acpi_os_printf("\n"); - return; - } - - buf_char = buffer[(acpi_size) i + j]; - if (ACPI_IS_PRINT(buf_char)) { - acpi_os_printf("%c", buf_char); - } else { - acpi_os_printf("."); - } - } - - /* Done with that line. */ - - acpi_os_printf("\n"); - i += 16; - } - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_dump_buffer - * - * PARAMETERS: Buffer - Buffer to dump - * Count - Amount to dump, in bytes - * Display - BYTE, WORD, DWORD, or QWORD display - * component_iD - Caller's component ID - * - * RETURN: None - * - * DESCRIPTION: Generic dump buffer in both hex and ascii. - * - ******************************************************************************/ - -void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) -{ - - /* Only dump the buffer if tracing is enabled */ - - if (!((ACPI_LV_TABLES & acpi_dbg_level) && - (component_id & acpi_dbg_layer))) { - return; - } - - acpi_ut_dump_buffer2(buffer, count, display); -} diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c deleted file mode 100644 index 5b4e3b1a7523..000000000000 --- a/drivers/acpi/utilities/utdelete.c +++ /dev/null @@ -1,677 +0,0 @@ -/******************************************************************************* - * - * Module Name: utdelete - object deletion and reference count utilities - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utdelete") - -/* Local prototypes */ -static void acpi_ut_delete_internal_obj(union acpi_operand_object *object); - -static void -acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action); - -/******************************************************************************* - * - * FUNCTION: acpi_ut_delete_internal_obj - * - * PARAMETERS: Object - Object to be deleted - * - * RETURN: None - * - * DESCRIPTION: Low level object deletion, after reference counts have been - * updated (All reference counts, including sub-objects!) - * - ******************************************************************************/ - -static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) -{ - void *obj_pointer = NULL; - union acpi_operand_object *handler_desc; - union acpi_operand_object *second_desc; - union acpi_operand_object *next_desc; - - ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object); - - if (!object) { - return_VOID; - } - - /* - * Must delete or free any pointers within the object that are not - * actual ACPI objects (for example, a raw buffer pointer). - */ - switch (ACPI_GET_OBJECT_TYPE(object)) { - case ACPI_TYPE_STRING: - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "**** String %p, ptr %p\n", object, - object->string.pointer)); - - /* Free the actual string buffer */ - - if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { - - /* But only if it is NOT a pointer into an ACPI table */ - - obj_pointer = object->string.pointer; - } - break; - - case ACPI_TYPE_BUFFER: - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "**** Buffer %p, ptr %p\n", object, - object->buffer.pointer)); - - /* Free the actual buffer */ - - if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { - - /* But only if it is NOT a pointer into an ACPI table */ - - obj_pointer = object->buffer.pointer; - } - break; - - case ACPI_TYPE_PACKAGE: - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - " **** Package of count %X\n", - object->package.count)); - - /* - * Elements of the package are not handled here, they are deleted - * separately - */ - - /* Free the (variable length) element pointer array */ - - obj_pointer = object->package.elements; - break; - - /* - * These objects have a possible list of notify handlers. - * Device object also may have a GPE block. - */ - case ACPI_TYPE_DEVICE: - - if (object->device.gpe_block) { - (void)acpi_ev_delete_gpe_block(object->device. - gpe_block); - } - - /*lint -fallthrough */ - - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_THERMAL: - - /* Walk the notify handler list for this object */ - - handler_desc = object->common_notify.handler; - while (handler_desc) { - next_desc = handler_desc->address_space.next; - acpi_ut_remove_reference(handler_desc); - handler_desc = next_desc; - } - break; - - case ACPI_TYPE_MUTEX: - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "***** Mutex %p, OS Mutex %p\n", - object, object->mutex.os_mutex)); - - if (object == acpi_gbl_global_lock_mutex) { - - /* Global Lock has extra semaphore */ - - (void) - acpi_os_delete_semaphore - (acpi_gbl_global_lock_semaphore); - acpi_gbl_global_lock_semaphore = NULL; - - acpi_os_delete_mutex(object->mutex.os_mutex); - acpi_gbl_global_lock_mutex = NULL; - } else { - acpi_ex_unlink_mutex(object); - acpi_os_delete_mutex(object->mutex.os_mutex); - } - break; - - case ACPI_TYPE_EVENT: - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "***** Event %p, OS Semaphore %p\n", - object, object->event.os_semaphore)); - - (void)acpi_os_delete_semaphore(object->event.os_semaphore); - object->event.os_semaphore = NULL; - break; - - case ACPI_TYPE_METHOD: - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "***** Method %p\n", object)); - - /* Delete the method mutex if it exists */ - - if (object->method.mutex) { - acpi_os_delete_mutex(object->method.mutex->mutex. - os_mutex); - acpi_ut_delete_object_desc(object->method.mutex); - object->method.mutex = NULL; - } - break; - - case ACPI_TYPE_REGION: - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "***** Region %p\n", object)); - - second_desc = acpi_ns_get_secondary_object(object); - if (second_desc) { - /* - * Free the region_context if and only if the handler is one of the - * default handlers -- and therefore, we created the context object - * locally, it was not created by an external caller. - */ - handler_desc = object->region.handler; - if (handler_desc) { - if (handler_desc->address_space.handler_flags & - ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { - - /* Deactivate region and free region context */ - - if (handler_desc->address_space.setup) { - (void)handler_desc-> - address_space.setup(object, - ACPI_REGION_DEACTIVATE, - handler_desc-> - address_space. - context, - &second_desc-> - extra. - region_context); - } - } - - acpi_ut_remove_reference(handler_desc); - } - - /* Now we can free the Extra object */ - - acpi_ut_delete_object_desc(second_desc); - } - break; - - case ACPI_TYPE_BUFFER_FIELD: - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "***** Buffer Field %p\n", object)); - - second_desc = acpi_ns_get_secondary_object(object); - if (second_desc) { - acpi_ut_delete_object_desc(second_desc); - } - break; - - case ACPI_TYPE_LOCAL_BANK_FIELD: - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "***** Bank Field %p\n", object)); - - second_desc = acpi_ns_get_secondary_object(object); - if (second_desc) { - acpi_ut_delete_object_desc(second_desc); - } - break; - - default: - break; - } - - /* Free any allocated memory (pointer within the object) found above */ - - if (obj_pointer) { - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Deleting Object Subptr %p\n", obj_pointer)); - ACPI_FREE(obj_pointer); - } - - /* Now the object can be safely deleted */ - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n", - object, acpi_ut_get_object_type_name(object))); - - acpi_ut_delete_object_desc(object); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_delete_internal_object_list - * - * PARAMETERS: obj_list - Pointer to the list to be deleted - * - * RETURN: None - * - * DESCRIPTION: This function deletes an internal object list, including both - * simple objects and package objects - * - ******************************************************************************/ - -void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list) -{ - union acpi_operand_object **internal_obj; - - ACPI_FUNCTION_TRACE(ut_delete_internal_object_list); - - /* Walk the null-terminated internal list */ - - for (internal_obj = obj_list; *internal_obj; internal_obj++) { - acpi_ut_remove_reference(*internal_obj); - } - - /* Free the combined parameter pointer list and object array */ - - ACPI_FREE(obj_list); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_update_ref_count - * - * PARAMETERS: Object - Object whose ref count is to be updated - * Action - What to do - * - * RETURN: New ref count - * - * DESCRIPTION: Modify the ref count and return it. - * - ******************************************************************************/ - -static void -acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) -{ - u16 count; - u16 new_count; - - ACPI_FUNCTION_NAME(ut_update_ref_count); - - if (!object) { - return; - } - - count = object->common.reference_count; - new_count = count; - - /* - * Perform the reference count action (increment, decrement, force delete) - */ - switch (action) { - case REF_INCREMENT: - - new_count++; - object->common.reference_count = new_count; - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Obj %p Refs=%X, [Incremented]\n", - object, new_count)); - break; - - case REF_DECREMENT: - - if (count < 1) { - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Obj %p Refs=%X, can't decrement! (Set to 0)\n", - object, new_count)); - - new_count = 0; - } else { - new_count--; - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Obj %p Refs=%X, [Decremented]\n", - object, new_count)); - } - - if (ACPI_GET_OBJECT_TYPE(object) == ACPI_TYPE_METHOD) { - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Method Obj %p Refs=%X, [Decremented]\n", - object, new_count)); - } - - object->common.reference_count = new_count; - if (new_count == 0) { - acpi_ut_delete_internal_obj(object); - } - break; - - case REF_FORCE_DELETE: - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Obj %p Refs=%X, Force delete! (Set to 0)\n", - object, count)); - - new_count = 0; - object->common.reference_count = new_count; - acpi_ut_delete_internal_obj(object); - break; - - default: - - ACPI_ERROR((AE_INFO, "Unknown action (%X)", action)); - break; - } - - /* - * Sanity check the reference count, for debug purposes only. - * (A deleted object will have a huge reference count) - */ - if (count > ACPI_MAX_REFERENCE_COUNT) { - ACPI_WARNING((AE_INFO, - "Large Reference Count (%X) in object %p", count, - object)); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_update_object_reference - * - * PARAMETERS: Object - Increment ref count for this object - * and all sub-objects - * Action - Either REF_INCREMENT or REF_DECREMENT or - * REF_FORCE_DELETE - * - * RETURN: Status - * - * DESCRIPTION: Increment the object reference count - * - * Object references are incremented when: - * 1) An object is attached to a Node (namespace object) - * 2) An object is copied (all subobjects must be incremented) - * - * Object references are decremented when: - * 1) An object is detached from an Node - * - ******************************************************************************/ - -acpi_status -acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) -{ - acpi_status status = AE_OK; - union acpi_generic_state *state_list = NULL; - union acpi_operand_object *next_object = NULL; - union acpi_generic_state *state; - u32 i; - - ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object); - - while (object) { - - /* Make sure that this isn't a namespace handle */ - - if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Object %p is NS handle\n", object)); - return_ACPI_STATUS(AE_OK); - } - - /* - * All sub-objects must have their reference count incremented also. - * Different object types have different subobjects. - */ - switch (ACPI_GET_OBJECT_TYPE(object)) { - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_POWER: - case ACPI_TYPE_THERMAL: - - /* Update the notify objects for these types (if present) */ - - acpi_ut_update_ref_count(object->common_notify. - system_notify, action); - acpi_ut_update_ref_count(object->common_notify. - device_notify, action); - break; - - case ACPI_TYPE_PACKAGE: - /* - * We must update all the sub-objects of the package, - * each of whom may have their own sub-objects. - */ - for (i = 0; i < object->package.count; i++) { - /* - * Push each element onto the stack for later processing. - * Note: There can be null elements within the package, - * these are simply ignored - */ - status = - acpi_ut_create_update_state_and_push - (object->package.elements[i], action, - &state_list); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - } - break; - - case ACPI_TYPE_BUFFER_FIELD: - - next_object = object->buffer_field.buffer_obj; - break; - - case ACPI_TYPE_LOCAL_REGION_FIELD: - - next_object = object->field.region_obj; - break; - - case ACPI_TYPE_LOCAL_BANK_FIELD: - - next_object = object->bank_field.bank_obj; - status = - acpi_ut_create_update_state_and_push(object-> - bank_field. - region_obj, - action, - &state_list); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - break; - - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - next_object = object->index_field.index_obj; - status = - acpi_ut_create_update_state_and_push(object-> - index_field. - data_obj, - action, - &state_list); - if (ACPI_FAILURE(status)) { - goto error_exit; - } - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - /* - * The target of an Index (a package, string, or buffer) or a named - * reference must track changes to the ref count of the index or - * target object. - */ - if ((object->reference.class == ACPI_REFCLASS_INDEX) || - (object->reference.class == ACPI_REFCLASS_NAME)) { - next_object = object->reference.object; - } - break; - - case ACPI_TYPE_REGION: - default: - break; /* No subobjects for all other types */ - } - - /* - * Now we can update the count in the main object. This can only - * happen after we update the sub-objects in case this causes the - * main object to be deleted. - */ - acpi_ut_update_ref_count(object, action); - object = NULL; - - /* Move on to the next object to be updated */ - - if (next_object) { - object = next_object; - next_object = NULL; - } else if (state_list) { - state = acpi_ut_pop_generic_state(&state_list); - object = state->update.object; - acpi_ut_delete_generic_state(state); - } - } - - return_ACPI_STATUS(AE_OK); - - error_exit: - - ACPI_EXCEPTION((AE_INFO, status, - "Could not update object reference count")); - - /* Free any stacked Update State objects */ - - while (state_list) { - state = acpi_ut_pop_generic_state(&state_list); - acpi_ut_delete_generic_state(state); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_add_reference - * - * PARAMETERS: Object - Object whose reference count is to be - * incremented - * - * RETURN: None - * - * DESCRIPTION: Add one reference to an ACPI object - * - ******************************************************************************/ - -void acpi_ut_add_reference(union acpi_operand_object *object) -{ - - ACPI_FUNCTION_TRACE_PTR(ut_add_reference, object); - - /* Ensure that we have a valid object */ - - if (!acpi_ut_valid_internal_object(object)) { - return_VOID; - } - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Obj %p Current Refs=%X [To Be Incremented]\n", - object, object->common.reference_count)); - - /* Increment the reference count */ - - (void)acpi_ut_update_object_reference(object, REF_INCREMENT); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_remove_reference - * - * PARAMETERS: Object - Object whose ref count will be decremented - * - * RETURN: None - * - * DESCRIPTION: Decrement the reference count of an ACPI internal object - * - ******************************************************************************/ - -void acpi_ut_remove_reference(union acpi_operand_object *object) -{ - - ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object); - - /* - * Allow a NULL pointer to be passed in, just ignore it. This saves - * each caller from having to check. Also, ignore NS nodes. - * - */ - if (!object || - (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED)) { - return_VOID; - } - - /* Ensure that we have a valid object */ - - if (!acpi_ut_valid_internal_object(object)) { - return_VOID; - } - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Obj %p Current Refs=%X [To Be Decremented]\n", - object, object->common.reference_count)); - - /* - * Decrement the reference count, and only actually delete the object - * if the reference count becomes 0. (Must also decrement the ref count - * of all subobjects!) - */ - (void)acpi_ut_update_object_reference(object, REF_DECREMENT); - return_VOID; -} diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c deleted file mode 100644 index e1e438cd54a9..000000000000 --- a/drivers/acpi/utilities/uteval.c +++ /dev/null @@ -1,752 +0,0 @@ -/****************************************************************************** - * - * Module Name: uteval - Object evaluation - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("uteval") - -/* Local prototypes */ -static void -acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length); - -static acpi_status -acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, - struct acpi_compatible_id *one_cid); - -/* - * Strings supported by the _OSI predefined (internal) method. - */ -static char *acpi_interfaces_supported[] = { - /* Operating System Vendor Strings */ - - "Windows 2000", /* Windows 2000 */ - "Windows 2001", /* Windows XP */ - "Windows 2001 SP1", /* Windows XP SP1 */ - "Windows 2001 SP2", /* Windows XP SP2 */ - "Windows 2001.1", /* Windows Server 2003 */ - "Windows 2001.1 SP1", /* Windows Server 2003 SP1 - Added 03/2006 */ - "Windows 2006", /* Windows Vista - Added 03/2006 */ - - /* Feature Group Strings */ - - "Extended Address Space Descriptor" - /* - * All "optional" feature group strings (features that are implemented - * by the host) should be implemented in the host version of - * acpi_os_validate_interface and should not be added here. - */ -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ut_osi_implementation - * - * PARAMETERS: walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: Implementation of the _OSI predefined control method - * - ******************************************************************************/ - -acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) -{ - acpi_status status; - union acpi_operand_object *string_desc; - union acpi_operand_object *return_desc; - u32 i; - - ACPI_FUNCTION_TRACE(ut_osi_implementation); - - /* Validate the string input argument */ - - string_desc = walk_state->arguments[0].object; - if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) { - return_ACPI_STATUS(AE_TYPE); - } - - /* Create a return object */ - - return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!return_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Default return value is SUPPORTED */ - - return_desc->integer.value = ACPI_UINT32_MAX; - walk_state->return_desc = return_desc; - - /* Compare input string to static table of supported interfaces */ - - for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { - if (!ACPI_STRCMP - (string_desc->string.pointer, - acpi_interfaces_supported[i])) { - - /* The interface is supported */ - - return_ACPI_STATUS(AE_OK); - } - } - - /* - * Did not match the string in the static table, call the host OSL to - * check for a match with one of the optional strings (such as - * "Module Device", "3.0 Thermal Model", etc.) - */ - status = acpi_os_validate_interface(string_desc->string.pointer); - if (ACPI_SUCCESS(status)) { - - /* The interface is supported */ - - return_ACPI_STATUS(AE_OK); - } - - /* The interface is not supported */ - - return_desc->integer.value = 0; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_osi_invalidate - * - * PARAMETERS: interface_string - * - * RETURN: Status - * - * DESCRIPTION: invalidate string in pre-defiend _OSI string list - * - ******************************************************************************/ - -acpi_status acpi_osi_invalidate(char *interface) -{ - int i; - - for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { - if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i])) { - *acpi_interfaces_supported[i] = '\0'; - return AE_OK; - } - } - return AE_NOT_FOUND; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_evaluate_object - * - * PARAMETERS: prefix_node - Starting node - * Path - Path to object from starting node - * expected_return_types - Bitmap of allowed return types - * return_desc - Where a return value is stored - * - * RETURN: Status - * - * DESCRIPTION: Evaluates a namespace object and verifies the type of the - * return object. Common code that simplifies accessing objects - * that have required return objects of fixed types. - * - * NOTE: Internal function, no parameter validation - * - ******************************************************************************/ - -acpi_status -acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, - char *path, - u32 expected_return_btypes, - union acpi_operand_object **return_desc) -{ - struct acpi_evaluate_info *info; - acpi_status status; - u32 return_btype; - - ACPI_FUNCTION_TRACE(ut_evaluate_object); - - /* Allocate the evaluation information block */ - - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); - if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - info->prefix_node = prefix_node; - info->pathname = path; - - /* Evaluate the object/method */ - - status = acpi_ns_evaluate(info); - if (ACPI_FAILURE(status)) { - if (status == AE_NOT_FOUND) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[%4.4s.%s] was not found\n", - acpi_ut_get_node_name(prefix_node), - path)); - } else { - ACPI_ERROR_METHOD("Method execution failed", - prefix_node, path, status); - } - - goto cleanup; - } - - /* Did we get a return object? */ - - if (!info->return_object) { - if (expected_return_btypes) { - ACPI_ERROR_METHOD("No object was returned from", - prefix_node, path, AE_NOT_EXIST); - - status = AE_NOT_EXIST; - } - - goto cleanup; - } - - /* Map the return object type to the bitmapped type */ - - switch (ACPI_GET_OBJECT_TYPE(info->return_object)) { - case ACPI_TYPE_INTEGER: - return_btype = ACPI_BTYPE_INTEGER; - break; - - case ACPI_TYPE_BUFFER: - return_btype = ACPI_BTYPE_BUFFER; - break; - - case ACPI_TYPE_STRING: - return_btype = ACPI_BTYPE_STRING; - break; - - case ACPI_TYPE_PACKAGE: - return_btype = ACPI_BTYPE_PACKAGE; - break; - - default: - return_btype = 0; - break; - } - - if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) { - /* - * We received a return object, but one was not expected. This can - * happen frequently if the "implicit return" feature is enabled. - * Just delete the return object and return AE_OK. - */ - acpi_ut_remove_reference(info->return_object); - goto cleanup; - } - - /* Is the return object one of the expected types? */ - - if (!(expected_return_btypes & return_btype)) { - ACPI_ERROR_METHOD("Return object type is incorrect", - prefix_node, path, AE_TYPE); - - ACPI_ERROR((AE_INFO, - "Type returned from %s was incorrect: %s, expected Btypes: %X", - path, - acpi_ut_get_object_type_name(info->return_object), - expected_return_btypes)); - - /* On error exit, we must delete the return object */ - - acpi_ut_remove_reference(info->return_object); - status = AE_TYPE; - goto cleanup; - } - - /* Object type is OK, return it */ - - *return_desc = info->return_object; - - cleanup: - ACPI_FREE(info); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_evaluate_numeric_object - * - * PARAMETERS: object_name - Object name to be evaluated - * device_node - Node for the device - * Address - Where the value is returned - * - * RETURN: Status - * - * DESCRIPTION: Evaluates a numeric namespace object for a selected device - * and stores result in *Address. - * - * NOTE: Internal function, no parameter validation - * - ******************************************************************************/ - -acpi_status -acpi_ut_evaluate_numeric_object(char *object_name, - struct acpi_namespace_node *device_node, - acpi_integer * address) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object); - - status = acpi_ut_evaluate_object(device_node, object_name, - ACPI_BTYPE_INTEGER, &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get the returned Integer */ - - *address = obj_desc->integer.value; - - /* On exit, we must delete the return object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_id_string - * - * PARAMETERS: Destination - Where to copy the string - * Source - Source string - * max_length - Length of the destination buffer - * - * RETURN: None - * - * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods. - * Performs removal of a leading asterisk if present -- workaround - * for a known issue on a bunch of machines. - * - ******************************************************************************/ - -static void -acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length) -{ - - /* - * Workaround for ID strings that have a leading asterisk. This construct - * is not allowed by the ACPI specification (ID strings must be - * alphanumeric), but enough existing machines have this embedded in their - * ID strings that the following code is useful. - */ - if (*source == '*') { - source++; - } - - /* Do the actual copy */ - - ACPI_STRNCPY(destination, source, max_length); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_execute_HID - * - * PARAMETERS: device_node - Node for the device - * Hid - Where the HID is returned - * - * RETURN: Status - * - * DESCRIPTION: Executes the _HID control method that returns the hardware - * ID of the device. - * - * NOTE: Internal function, no parameter validation - * - ******************************************************************************/ - -acpi_status -acpi_ut_execute_HID(struct acpi_namespace_node *device_node, - struct acpica_device_id *hid) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_execute_HID); - - status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID, - ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, - &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { - - /* Convert the Numeric HID to string */ - - acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value, - hid->value); - } else { - /* Copy the String HID from the returned object */ - - acpi_ut_copy_id_string(hid->value, obj_desc->string.pointer, - sizeof(hid->value)); - } - - /* On exit, we must delete the return object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_translate_one_cid - * - * PARAMETERS: obj_desc - _CID object, must be integer or string - * one_cid - Where the CID string is returned - * - * RETURN: Status - * - * DESCRIPTION: Return a numeric or string _CID value as a string. - * (Compatible ID) - * - * NOTE: Assumes a maximum _CID string length of - * ACPI_MAX_CID_LENGTH. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, - struct acpi_compatible_id *one_cid) -{ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_INTEGER: - - /* Convert the Numeric CID to string */ - - acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value, - one_cid->value); - return (AE_OK); - - case ACPI_TYPE_STRING: - - if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) { - return (AE_AML_STRING_LIMIT); - } - - /* Copy the String CID from the returned object */ - - acpi_ut_copy_id_string(one_cid->value, obj_desc->string.pointer, - ACPI_MAX_CID_LENGTH); - return (AE_OK); - - default: - - return (AE_TYPE); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_execute_CID - * - * PARAMETERS: device_node - Node for the device - * return_cid_list - Where the CID list is returned - * - * RETURN: Status - * - * DESCRIPTION: Executes the _CID control method that returns one or more - * compatible hardware IDs for the device. - * - * NOTE: Internal function, no parameter validation - * - ******************************************************************************/ - -acpi_status -acpi_ut_execute_CID(struct acpi_namespace_node * device_node, - struct acpi_compatible_id_list ** return_cid_list) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - u32 count; - u32 size; - struct acpi_compatible_id_list *cid_list; - u32 i; - - ACPI_FUNCTION_TRACE(ut_execute_CID); - - /* Evaluate the _CID method for this device */ - - status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID, - ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING - | ACPI_BTYPE_PACKAGE, &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get the number of _CIDs returned */ - - count = 1; - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { - count = obj_desc->package.count; - } - - /* Allocate a worst-case buffer for the _CIDs */ - - size = (((count - 1) * sizeof(struct acpi_compatible_id)) + - sizeof(struct acpi_compatible_id_list)); - - cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); - if (!cid_list) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Init CID list */ - - cid_list->count = count; - cid_list->size = size; - - /* - * A _CID can return either a single compatible ID or a package of - * compatible IDs. Each compatible ID can be one of the following: - * 1) Integer (32 bit compressed EISA ID) or - * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss") - */ - - /* The _CID object can be either a single CID or a package (list) of CIDs */ - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { - - /* Translate each package element */ - - for (i = 0; i < count; i++) { - status = - acpi_ut_translate_one_cid(obj_desc->package. - elements[i], - &cid_list->id[i]); - if (ACPI_FAILURE(status)) { - break; - } - } - } else { - /* Only one CID, translate to a string */ - - status = acpi_ut_translate_one_cid(obj_desc, cid_list->id); - } - - /* Cleanup on error */ - - if (ACPI_FAILURE(status)) { - ACPI_FREE(cid_list); - } else { - *return_cid_list = cid_list; - } - - /* On exit, we must delete the _CID return object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_execute_UID - * - * PARAMETERS: device_node - Node for the device - * Uid - Where the UID is returned - * - * RETURN: Status - * - * DESCRIPTION: Executes the _UID control method that returns the hardware - * ID of the device. - * - * NOTE: Internal function, no parameter validation - * - ******************************************************************************/ - -acpi_status -acpi_ut_execute_UID(struct acpi_namespace_node *device_node, - struct acpica_device_id *uid) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_execute_UID); - - status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID, - ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, - &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { - - /* Convert the Numeric UID to string */ - - acpi_ex_unsigned_integer_to_string(obj_desc->integer.value, - uid->value); - } else { - /* Copy the String UID from the returned object */ - - acpi_ut_copy_id_string(uid->value, obj_desc->string.pointer, - sizeof(uid->value)); - } - - /* On exit, we must delete the return object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_execute_STA - * - * PARAMETERS: device_node - Node for the device - * Flags - Where the status flags are returned - * - * RETURN: Status - * - * DESCRIPTION: Executes _STA for selected device and stores results in - * *Flags. - * - * NOTE: Internal function, no parameter validation - * - ******************************************************************************/ - -acpi_status -acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_execute_STA); - - status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA, - ACPI_BTYPE_INTEGER, &obj_desc); - if (ACPI_FAILURE(status)) { - if (AE_NOT_FOUND == status) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "_STA on %4.4s was not found, assuming device is present\n", - acpi_ut_get_node_name(device_node))); - - *flags = ACPI_UINT32_MAX; - status = AE_OK; - } - - return_ACPI_STATUS(status); - } - - /* Extract the status flags */ - - *flags = (u32) obj_desc->integer.value; - - /* On exit, we must delete the return object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_execute_Sxds - * - * PARAMETERS: device_node - Node for the device - * Flags - Where the status flags are returned - * - * RETURN: Status - * - * DESCRIPTION: Executes _STA for selected device and stores results in - * *Flags. - * - * NOTE: Internal function, no parameter validation - * - ******************************************************************************/ - -acpi_status -acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest) -{ - union acpi_operand_object *obj_desc; - acpi_status status; - u32 i; - - ACPI_FUNCTION_TRACE(ut_execute_sxds); - - for (i = 0; i < 4; i++) { - highest[i] = 0xFF; - status = acpi_ut_evaluate_object(device_node, - ACPI_CAST_PTR(char, - acpi_gbl_highest_dstate_names - [i]), - ACPI_BTYPE_INTEGER, &obj_desc); - if (ACPI_FAILURE(status)) { - if (status != AE_NOT_FOUND) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "%s on Device %4.4s, %s\n", - ACPI_CAST_PTR(char, - acpi_gbl_highest_dstate_names - [i]), - acpi_ut_get_node_name - (device_node), - acpi_format_exception - (status))); - - return_ACPI_STATUS(status); - } - } else { - /* Extract the Dstate value */ - - highest[i] = (u8) obj_desc->integer.value; - - /* Delete the return object */ - - acpi_ut_remove_reference(obj_desc); - } - } - - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c deleted file mode 100644 index 3e28d8c4045d..000000000000 --- a/drivers/acpi/utilities/utglobal.c +++ /dev/null @@ -1,823 +0,0 @@ -/****************************************************************************** - * - * Module Name: utglobal - Global variables for the ACPI subsystem - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#define DEFINE_ACPI_GLOBALS - -#include -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utglobal") - -/******************************************************************************* - * - * Static global variable initialization. - * - ******************************************************************************/ -/* - * We want the debug switches statically initialized so they - * are already set when the debugger is entered. - */ -/* Debug switch - level and trace mask */ -u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT; - -/* Debug switch - layer (component) mask */ - -u32 acpi_dbg_layer = 0; -u32 acpi_gbl_nesting_level = 0; - -/* Debugger globals */ - -u8 acpi_gbl_db_terminate_threads = FALSE; -u8 acpi_gbl_abort_method = FALSE; -u8 acpi_gbl_method_executing = FALSE; - -/* System flags */ - -u32 acpi_gbl_startup_flags = 0; - -/* System starts uninitialized */ - -u8 acpi_gbl_shutdown = TRUE; - -const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = { - "\\_S0_", - "\\_S1_", - "\\_S2_", - "\\_S3_", - "\\_S4_", - "\\_S5_" -}; - -const char *acpi_gbl_highest_dstate_names[4] = { - "_S1D", - "_S2D", - "_S3D", - "_S4D" -}; - -/******************************************************************************* - * - * FUNCTION: acpi_format_exception - * - * PARAMETERS: Status - The acpi_status code to be formatted - * - * RETURN: A string containing the exception text. A valid pointer is - * always returned. - * - * DESCRIPTION: This function translates an ACPI exception into an ASCII string - * It is here instead of utxface.c so it is always present. - * - ******************************************************************************/ - -const char *acpi_format_exception(acpi_status status) -{ - const char *exception = NULL; - - ACPI_FUNCTION_ENTRY(); - - exception = acpi_ut_validate_exception(status); - if (!exception) { - - /* Exception code was not recognized */ - - ACPI_ERROR((AE_INFO, - "Unknown exception code: 0x%8.8X", status)); - - exception = "UNKNOWN_STATUS_CODE"; - dump_stack(); - } - - return (ACPI_CAST_PTR(const char, exception)); -} - -ACPI_EXPORT_SYMBOL(acpi_format_exception) - -/******************************************************************************* - * - * Namespace globals - * - ******************************************************************************/ -/* - * Predefined ACPI Names (Built-in to the Interpreter) - * - * NOTES: - * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run - * during the initialization sequence. - * 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to - * perform a Notify() operation on it. - */ -const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = { - {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL}, - {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL}, - {"_SB_", ACPI_TYPE_DEVICE, NULL}, - {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL}, - {"_TZ_", ACPI_TYPE_THERMAL, NULL}, - {"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL}, - {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, - {"_GL_", ACPI_TYPE_MUTEX, (char *)1}, - -#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) - {"_OSI", ACPI_TYPE_METHOD, (char *)1}, -#endif - - /* Table terminator */ - - {NULL, ACPI_TYPE_ANY, NULL} -}; - -/* - * Properties of the ACPI Object Types, both internal and external. - * The table is indexed by values of acpi_object_type - */ -const u8 acpi_gbl_ns_properties[] = { - ACPI_NS_NORMAL, /* 00 Any */ - ACPI_NS_NORMAL, /* 01 Number */ - ACPI_NS_NORMAL, /* 02 String */ - ACPI_NS_NORMAL, /* 03 Buffer */ - ACPI_NS_NORMAL, /* 04 Package */ - ACPI_NS_NORMAL, /* 05 field_unit */ - ACPI_NS_NEWSCOPE, /* 06 Device */ - ACPI_NS_NORMAL, /* 07 Event */ - ACPI_NS_NEWSCOPE, /* 08 Method */ - ACPI_NS_NORMAL, /* 09 Mutex */ - ACPI_NS_NORMAL, /* 10 Region */ - ACPI_NS_NEWSCOPE, /* 11 Power */ - ACPI_NS_NEWSCOPE, /* 12 Processor */ - ACPI_NS_NEWSCOPE, /* 13 Thermal */ - ACPI_NS_NORMAL, /* 14 buffer_field */ - ACPI_NS_NORMAL, /* 15 ddb_handle */ - ACPI_NS_NORMAL, /* 16 Debug Object */ - ACPI_NS_NORMAL, /* 17 def_field */ - ACPI_NS_NORMAL, /* 18 bank_field */ - ACPI_NS_NORMAL, /* 19 index_field */ - ACPI_NS_NORMAL, /* 20 Reference */ - ACPI_NS_NORMAL, /* 21 Alias */ - ACPI_NS_NORMAL, /* 22 method_alias */ - ACPI_NS_NORMAL, /* 23 Notify */ - ACPI_NS_NORMAL, /* 24 Address Handler */ - ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */ - ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */ - ACPI_NS_NEWSCOPE, /* 27 Scope */ - ACPI_NS_NORMAL, /* 28 Extra */ - ACPI_NS_NORMAL, /* 29 Data */ - ACPI_NS_NORMAL /* 30 Invalid */ -}; - -/* Hex to ASCII conversion table */ - -static const char acpi_gbl_hex_to_ascii[] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ut_hex_to_ascii_char - * - * PARAMETERS: Integer - Contains the hex digit - * Position - bit position of the digit within the - * integer (multiple of 4) - * - * RETURN: The converted Ascii character - * - * DESCRIPTION: Convert a hex digit to an Ascii character - * - ******************************************************************************/ - -char acpi_ut_hex_to_ascii_char(acpi_integer integer, u32 position) -{ - - return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); -} - -/****************************************************************************** - * - * Event and Hardware globals - * - ******************************************************************************/ - -struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] = { - /* Name Parent Register Register Bit Position Register Bit Mask */ - - /* ACPI_BITREG_TIMER_STATUS */ {ACPI_REGISTER_PM1_STATUS, - ACPI_BITPOSITION_TIMER_STATUS, - ACPI_BITMASK_TIMER_STATUS}, - /* ACPI_BITREG_BUS_MASTER_STATUS */ {ACPI_REGISTER_PM1_STATUS, - ACPI_BITPOSITION_BUS_MASTER_STATUS, - ACPI_BITMASK_BUS_MASTER_STATUS}, - /* ACPI_BITREG_GLOBAL_LOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, - ACPI_BITPOSITION_GLOBAL_LOCK_STATUS, - ACPI_BITMASK_GLOBAL_LOCK_STATUS}, - /* ACPI_BITREG_POWER_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, - ACPI_BITPOSITION_POWER_BUTTON_STATUS, - ACPI_BITMASK_POWER_BUTTON_STATUS}, - /* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, - ACPI_BITPOSITION_SLEEP_BUTTON_STATUS, - ACPI_BITMASK_SLEEP_BUTTON_STATUS}, - /* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, - ACPI_BITPOSITION_RT_CLOCK_STATUS, - ACPI_BITMASK_RT_CLOCK_STATUS}, - /* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, - ACPI_BITPOSITION_WAKE_STATUS, - ACPI_BITMASK_WAKE_STATUS}, - /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, - ACPI_BITPOSITION_PCIEXP_WAKE_STATUS, - ACPI_BITMASK_PCIEXP_WAKE_STATUS}, - - /* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, - ACPI_BITPOSITION_TIMER_ENABLE, - ACPI_BITMASK_TIMER_ENABLE}, - /* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, - ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE, - ACPI_BITMASK_GLOBAL_LOCK_ENABLE}, - /* ACPI_BITREG_POWER_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, - ACPI_BITPOSITION_POWER_BUTTON_ENABLE, - ACPI_BITMASK_POWER_BUTTON_ENABLE}, - /* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, - ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE, - ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, - /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, - ACPI_BITPOSITION_RT_CLOCK_ENABLE, - ACPI_BITMASK_RT_CLOCK_ENABLE}, - /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, - ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, - ACPI_BITMASK_PCIEXP_WAKE_DISABLE}, - - /* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, - ACPI_BITPOSITION_SCI_ENABLE, - ACPI_BITMASK_SCI_ENABLE}, - /* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL, - ACPI_BITPOSITION_BUS_MASTER_RLD, - ACPI_BITMASK_BUS_MASTER_RLD}, - /* ACPI_BITREG_GLOBAL_LOCK_RELEASE */ {ACPI_REGISTER_PM1_CONTROL, - ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE, - ACPI_BITMASK_GLOBAL_LOCK_RELEASE}, - /* ACPI_BITREG_SLEEP_TYPE_A */ {ACPI_REGISTER_PM1_CONTROL, - ACPI_BITPOSITION_SLEEP_TYPE_X, - ACPI_BITMASK_SLEEP_TYPE_X}, - /* ACPI_BITREG_SLEEP_TYPE_B */ {ACPI_REGISTER_PM1_CONTROL, - ACPI_BITPOSITION_SLEEP_TYPE_X, - ACPI_BITMASK_SLEEP_TYPE_X}, - /* ACPI_BITREG_SLEEP_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, - ACPI_BITPOSITION_SLEEP_ENABLE, - ACPI_BITMASK_SLEEP_ENABLE}, - - /* ACPI_BITREG_ARB_DIS */ {ACPI_REGISTER_PM2_CONTROL, - ACPI_BITPOSITION_ARB_DISABLE, - ACPI_BITMASK_ARB_DISABLE} -}; - -struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = { - /* ACPI_EVENT_PMTIMER */ {ACPI_BITREG_TIMER_STATUS, - ACPI_BITREG_TIMER_ENABLE, - ACPI_BITMASK_TIMER_STATUS, - ACPI_BITMASK_TIMER_ENABLE}, - /* ACPI_EVENT_GLOBAL */ {ACPI_BITREG_GLOBAL_LOCK_STATUS, - ACPI_BITREG_GLOBAL_LOCK_ENABLE, - ACPI_BITMASK_GLOBAL_LOCK_STATUS, - ACPI_BITMASK_GLOBAL_LOCK_ENABLE}, - /* ACPI_EVENT_POWER_BUTTON */ {ACPI_BITREG_POWER_BUTTON_STATUS, - ACPI_BITREG_POWER_BUTTON_ENABLE, - ACPI_BITMASK_POWER_BUTTON_STATUS, - ACPI_BITMASK_POWER_BUTTON_ENABLE}, - /* ACPI_EVENT_SLEEP_BUTTON */ {ACPI_BITREG_SLEEP_BUTTON_STATUS, - ACPI_BITREG_SLEEP_BUTTON_ENABLE, - ACPI_BITMASK_SLEEP_BUTTON_STATUS, - ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, - /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS, - ACPI_BITREG_RT_CLOCK_ENABLE, - ACPI_BITMASK_RT_CLOCK_STATUS, - ACPI_BITMASK_RT_CLOCK_ENABLE}, -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_region_name - * - * PARAMETERS: None. - * - * RETURN: Status - * - * DESCRIPTION: Translate a Space ID into a name string (Debug only) - * - ******************************************************************************/ - -/* Region type decoding */ - -const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { - "SystemMemory", - "SystemIO", - "PCI_Config", - "EmbeddedControl", - "SMBus", - "SystemCMOS", - "PCIBARTarget", - "DataTable" -}; - -char *acpi_ut_get_region_name(u8 space_id) -{ - - if (space_id >= ACPI_USER_REGION_BEGIN) { - return ("UserDefinedRegion"); - } else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) { - return ("InvalidSpaceId"); - } - - return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_event_name - * - * PARAMETERS: None. - * - * RETURN: Status - * - * DESCRIPTION: Translate a Event ID into a name string (Debug only) - * - ******************************************************************************/ - -/* Event type decoding */ - -static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { - "PM_Timer", - "GlobalLock", - "PowerButton", - "SleepButton", - "RealTimeClock", -}; - -char *acpi_ut_get_event_name(u32 event_id) -{ - - if (event_id > ACPI_EVENT_MAX) { - return ("InvalidEventID"); - } - - return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id])); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_type_name - * - * PARAMETERS: None. - * - * RETURN: Status - * - * DESCRIPTION: Translate a Type ID into a name string (Debug only) - * - ******************************************************************************/ - -/* - * Elements of acpi_gbl_ns_type_names below must match - * one-to-one with values of acpi_object_type - * - * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; - * when stored in a table it really means that we have thus far seen no - * evidence to indicate what type is actually going to be stored for this entry. - */ -static const char acpi_gbl_bad_type[] = "UNDEFINED"; - -/* Printable names of the ACPI object types */ - -static const char *acpi_gbl_ns_type_names[] = { - /* 00 */ "Untyped", - /* 01 */ "Integer", - /* 02 */ "String", - /* 03 */ "Buffer", - /* 04 */ "Package", - /* 05 */ "FieldUnit", - /* 06 */ "Device", - /* 07 */ "Event", - /* 08 */ "Method", - /* 09 */ "Mutex", - /* 10 */ "Region", - /* 11 */ "Power", - /* 12 */ "Processor", - /* 13 */ "Thermal", - /* 14 */ "BufferField", - /* 15 */ "DdbHandle", - /* 16 */ "DebugObject", - /* 17 */ "RegionField", - /* 18 */ "BankField", - /* 19 */ "IndexField", - /* 20 */ "Reference", - /* 21 */ "Alias", - /* 22 */ "MethodAlias", - /* 23 */ "Notify", - /* 24 */ "AddrHandler", - /* 25 */ "ResourceDesc", - /* 26 */ "ResourceFld", - /* 27 */ "Scope", - /* 28 */ "Extra", - /* 29 */ "Data", - /* 30 */ "Invalid" -}; - -char *acpi_ut_get_type_name(acpi_object_type type) -{ - - if (type > ACPI_TYPE_INVALID) { - return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); - } - - return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type])); -} - -char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) -{ - - if (!obj_desc) { - return ("[NULL Object Descriptor]"); - } - - return (acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc))); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_node_name - * - * PARAMETERS: Object - A namespace node - * - * RETURN: Pointer to a string - * - * DESCRIPTION: Validate the node and return the node's ACPI name. - * - ******************************************************************************/ - -char *acpi_ut_get_node_name(void *object) -{ - struct acpi_namespace_node *node = (struct acpi_namespace_node *)object; - - /* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */ - - if (!object) { - return ("NULL"); - } - - /* Check for Root node */ - - if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) { - return ("\"\\\" "); - } - - /* Descriptor must be a namespace node */ - - if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { - return ("####"); - } - - /* Name must be a valid ACPI name */ - - if (!acpi_ut_valid_acpi_name(node->name.integer)) { - node->name.integer = acpi_ut_repair_name(node->name.ascii); - } - - /* Return the name */ - - return (node->name.ascii); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_descriptor_name - * - * PARAMETERS: Object - An ACPI object - * - * RETURN: Pointer to a string - * - * DESCRIPTION: Validate object and return the descriptor type - * - ******************************************************************************/ - -/* Printable names of object descriptor types */ - -static const char *acpi_gbl_desc_type_names[] = { - /* 00 */ "Invalid", - /* 01 */ "Cached", - /* 02 */ "State-Generic", - /* 03 */ "State-Update", - /* 04 */ "State-Package", - /* 05 */ "State-Control", - /* 06 */ "State-RootParseScope", - /* 07 */ "State-ParseScope", - /* 08 */ "State-WalkScope", - /* 09 */ "State-Result", - /* 10 */ "State-Notify", - /* 11 */ "State-Thread", - /* 12 */ "Walk", - /* 13 */ "Parser", - /* 14 */ "Operand", - /* 15 */ "Node" -}; - -char *acpi_ut_get_descriptor_name(void *object) -{ - - if (!object) { - return ("NULL OBJECT"); - } - - if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) { - return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); - } - - return (ACPI_CAST_PTR(char, - acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE - (object)])); - -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_reference_name - * - * PARAMETERS: Object - An ACPI reference object - * - * RETURN: Pointer to a string - * - * DESCRIPTION: Decode a reference object sub-type to a string. - * - ******************************************************************************/ - -/* Printable names of reference object sub-types */ - -static const char *acpi_gbl_ref_class_names[] = { - /* 00 */ "Local", - /* 01 */ "Argument", - /* 02 */ "RefOf", - /* 03 */ "Index", - /* 04 */ "DdbHandle", - /* 05 */ "Named Object", - /* 06 */ "Debug" -}; - -const char *acpi_ut_get_reference_name(union acpi_operand_object *object) -{ - if (!object) - return "NULL Object"; - - if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) - return "Not an Operand object"; - - if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE) - return "Not a Reference object"; - - if (object->reference.class > ACPI_REFCLASS_MAX) - return "Unknown Reference class"; - - return acpi_gbl_ref_class_names[object->reference.class]; -} - -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) -/* - * Strings and procedures used for debug only - */ - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_mutex_name - * - * PARAMETERS: mutex_id - The predefined ID for this mutex. - * - * RETURN: String containing the name of the mutex. Always returns a valid - * pointer. - * - * DESCRIPTION: Translate a mutex ID into a name string (Debug only) - * - ******************************************************************************/ - -char *acpi_ut_get_mutex_name(u32 mutex_id) -{ - - if (mutex_id > ACPI_MAX_MUTEX) { - return ("Invalid Mutex ID"); - } - - return (acpi_gbl_mutex_names[mutex_id]); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_notify_name - * - * PARAMETERS: notify_value - Value from the Notify() request - * - * RETURN: String corresponding to the Notify Value. - * - * DESCRIPTION: Translate a Notify Value to a notify namestring. - * - ******************************************************************************/ - -/* Names for Notify() values, used for debug output */ - -static const char *acpi_gbl_notify_value_names[] = { - "Bus Check", - "Device Check", - "Device Wake", - "Eject Request", - "Device Check Light", - "Frequency Mismatch", - "Bus Mode Mismatch", - "Power Fault", - "Capabilities Check", - "Device PLD Check", - "Reserved", - "System Locality Update" -}; - -const char *acpi_ut_get_notify_name(u32 notify_value) -{ - - if (notify_value <= ACPI_NOTIFY_MAX) { - return (acpi_gbl_notify_value_names[notify_value]); - } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { - return ("Reserved"); - } else { /* Greater or equal to 0x80 */ - - return ("**Device Specific**"); - } -} -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ut_valid_object_type - * - * PARAMETERS: Type - Object type to be validated - * - * RETURN: TRUE if valid object type, FALSE otherwise - * - * DESCRIPTION: Validate an object type - * - ******************************************************************************/ - -u8 acpi_ut_valid_object_type(acpi_object_type type) -{ - - if (type > ACPI_TYPE_LOCAL_MAX) { - - /* Note: Assumes all TYPEs are contiguous (external/local) */ - - return (FALSE); - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_init_globals - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Init library globals. All globals that require specific - * initialization should be initialized here! - * - ******************************************************************************/ - -acpi_status acpi_ut_init_globals(void) -{ - acpi_status status; - u32 i; - - ACPI_FUNCTION_TRACE(ut_init_globals); - - /* Create all memory caches */ - - status = acpi_ut_create_caches(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Mutex locked flags */ - - for (i = 0; i < ACPI_NUM_MUTEX; i++) { - acpi_gbl_mutex_info[i].mutex = NULL; - acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED; - acpi_gbl_mutex_info[i].use_count = 0; - } - - for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { - acpi_gbl_owner_id_mask[i] = 0; - } - acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; /* Last ID is never valid */ - - /* GPE support */ - - acpi_gbl_gpe_xrupt_list_head = NULL; - acpi_gbl_gpe_fadt_blocks[0] = NULL; - acpi_gbl_gpe_fadt_blocks[1] = NULL; - acpi_current_gpe_count = 0; - - /* Global handlers */ - - acpi_gbl_system_notify.handler = NULL; - acpi_gbl_device_notify.handler = NULL; - acpi_gbl_exception_handler = NULL; - acpi_gbl_init_handler = NULL; - acpi_gbl_table_handler = NULL; - - /* Global Lock support */ - - acpi_gbl_global_lock_semaphore = NULL; - acpi_gbl_global_lock_mutex = NULL; - acpi_gbl_global_lock_acquired = FALSE; - acpi_gbl_global_lock_handle = 0; - acpi_gbl_global_lock_present = FALSE; - - /* Miscellaneous variables */ - - acpi_gbl_cm_single_step = FALSE; - acpi_gbl_db_terminate_threads = FALSE; - acpi_gbl_shutdown = FALSE; - acpi_gbl_ns_lookup_count = 0; - acpi_gbl_ps_find_count = 0; - acpi_gbl_acpi_hardware_present = TRUE; - acpi_gbl_last_owner_id_index = 0; - acpi_gbl_next_owner_id_offset = 0; - acpi_gbl_trace_method_name = 0; - acpi_gbl_trace_dbg_level = 0; - acpi_gbl_trace_dbg_layer = 0; - acpi_gbl_debugger_configuration = DEBUGGER_THREADING; - acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; - - /* Hardware oriented */ - - acpi_gbl_events_initialized = FALSE; - acpi_gbl_system_awake_and_running = TRUE; - - /* Namespace */ - - acpi_gbl_root_node = NULL; - acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; - acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; - acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE; - acpi_gbl_root_node_struct.child = NULL; - acpi_gbl_root_node_struct.peer = NULL; - acpi_gbl_root_node_struct.object = NULL; - acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST; - -#ifdef ACPI_DEBUG_OUTPUT - acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); -#endif - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - acpi_gbl_display_final_mem_stats = FALSE; -#endif - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) -ACPI_EXPORT_SYMBOL(acpi_dbg_level) -ACPI_EXPORT_SYMBOL(acpi_dbg_layer) -ACPI_EXPORT_SYMBOL(acpi_current_gpe_count) diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c deleted file mode 100644 index 9316ec36a836..000000000000 --- a/drivers/acpi/utilities/utinit.c +++ /dev/null @@ -1,152 +0,0 @@ -/****************************************************************************** - * - * Module Name: utinit - Common ACPI subsystem initialization - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utinit") - -/* Local prototypes */ -static void acpi_ut_terminate(void); - -/****************************************************************************** - * - * FUNCTION: acpi_ut_terminate - * - * PARAMETERS: none - * - * RETURN: none - * - * DESCRIPTION: Free global memory - * - ******************************************************************************/ - -static void acpi_ut_terminate(void) -{ - struct acpi_gpe_block_info *gpe_block; - struct acpi_gpe_block_info *next_gpe_block; - struct acpi_gpe_xrupt_info *gpe_xrupt_info; - struct acpi_gpe_xrupt_info *next_gpe_xrupt_info; - - ACPI_FUNCTION_TRACE(ut_terminate); - - /* Free global GPE blocks and related info structures */ - - gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; - while (gpe_xrupt_info) { - gpe_block = gpe_xrupt_info->gpe_block_list_head; - while (gpe_block) { - next_gpe_block = gpe_block->next; - ACPI_FREE(gpe_block->event_info); - ACPI_FREE(gpe_block->register_info); - ACPI_FREE(gpe_block); - - gpe_block = next_gpe_block; - } - next_gpe_xrupt_info = gpe_xrupt_info->next; - ACPI_FREE(gpe_xrupt_info); - gpe_xrupt_info = next_gpe_xrupt_info; - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_subsystem_shutdown - * - * PARAMETERS: none - * - * RETURN: none - * - * DESCRIPTION: Shutdown the various subsystems. Don't delete the mutex - * objects here -- because the AML debugger may be still running. - * - ******************************************************************************/ - -void acpi_ut_subsystem_shutdown(void) -{ - - ACPI_FUNCTION_TRACE(ut_subsystem_shutdown); - - /* Just exit if subsystem is already shutdown */ - - if (acpi_gbl_shutdown) { - ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated")); - return_VOID; - } - - /* Subsystem appears active, go ahead and shut it down */ - - acpi_gbl_shutdown = TRUE; - acpi_gbl_startup_flags = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); - -#ifndef ACPI_ASL_COMPILER - - /* Close the acpi_event Handling */ - - acpi_ev_terminate(); -#endif - - /* Close the Namespace */ - - acpi_ns_terminate(); - - /* Delete the ACPI tables */ - - acpi_tb_terminate(); - - /* Close the globals */ - - acpi_ut_terminate(); - - /* Purge the local caches */ - - (void)acpi_ut_delete_caches(); - return_VOID; -} diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c deleted file mode 100644 index 616d7b271c9a..000000000000 --- a/drivers/acpi/utilities/utmath.c +++ /dev/null @@ -1,312 +0,0 @@ -/******************************************************************************* - * - * Module Name: utmath - Integer math support routines - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utmath") - -/* - * Support for double-precision integer divide. This code is included here - * in order to support kernel environments where the double-precision math - * library is not available. - */ -#ifndef ACPI_USE_NATIVE_DIVIDE -/******************************************************************************* - * - * FUNCTION: acpi_ut_short_divide - * - * PARAMETERS: Dividend - 64-bit dividend - * Divisor - 32-bit divisor - * out_quotient - Pointer to where the quotient is returned - * out_remainder - Pointer to where the remainder is returned - * - * RETURN: Status (Checks for divide-by-zero) - * - * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits) - * divide and modulo. The result is a 64-bit quotient and a - * 32-bit remainder. - * - ******************************************************************************/ -acpi_status -acpi_ut_short_divide(acpi_integer dividend, - u32 divisor, - acpi_integer * out_quotient, u32 * out_remainder) -{ - union uint64_overlay dividend_ovl; - union uint64_overlay quotient; - u32 remainder32; - - ACPI_FUNCTION_TRACE(ut_short_divide); - - /* Always check for a zero divisor */ - - if (divisor == 0) { - ACPI_ERROR((AE_INFO, "Divide by zero")); - return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); - } - - dividend_ovl.full = dividend; - - /* - * The quotient is 64 bits, the remainder is always 32 bits, - * and is generated by the second divide. - */ - ACPI_DIV_64_BY_32(0, dividend_ovl.part.hi, divisor, - quotient.part.hi, remainder32); - ACPI_DIV_64_BY_32(remainder32, dividend_ovl.part.lo, divisor, - quotient.part.lo, remainder32); - - /* Return only what was requested */ - - if (out_quotient) { - *out_quotient = quotient.full; - } - if (out_remainder) { - *out_remainder = remainder32; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_divide - * - * PARAMETERS: in_dividend - Dividend - * in_divisor - Divisor - * out_quotient - Pointer to where the quotient is returned - * out_remainder - Pointer to where the remainder is returned - * - * RETURN: Status (Checks for divide-by-zero) - * - * DESCRIPTION: Perform a divide and modulo. - * - ******************************************************************************/ - -acpi_status -acpi_ut_divide(acpi_integer in_dividend, - acpi_integer in_divisor, - acpi_integer * out_quotient, acpi_integer * out_remainder) -{ - union uint64_overlay dividend; - union uint64_overlay divisor; - union uint64_overlay quotient; - union uint64_overlay remainder; - union uint64_overlay normalized_dividend; - union uint64_overlay normalized_divisor; - u32 partial1; - union uint64_overlay partial2; - union uint64_overlay partial3; - - ACPI_FUNCTION_TRACE(ut_divide); - - /* Always check for a zero divisor */ - - if (in_divisor == 0) { - ACPI_ERROR((AE_INFO, "Divide by zero")); - return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); - } - - divisor.full = in_divisor; - dividend.full = in_dividend; - if (divisor.part.hi == 0) { - /* - * 1) Simplest case is where the divisor is 32 bits, we can - * just do two divides - */ - remainder.part.hi = 0; - - /* - * The quotient is 64 bits, the remainder is always 32 bits, - * and is generated by the second divide. - */ - ACPI_DIV_64_BY_32(0, dividend.part.hi, divisor.part.lo, - quotient.part.hi, partial1); - ACPI_DIV_64_BY_32(partial1, dividend.part.lo, divisor.part.lo, - quotient.part.lo, remainder.part.lo); - } - - else { - /* - * 2) The general case where the divisor is a full 64 bits - * is more difficult - */ - quotient.part.hi = 0; - normalized_dividend = dividend; - normalized_divisor = divisor; - - /* Normalize the operands (shift until the divisor is < 32 bits) */ - - do { - ACPI_SHIFT_RIGHT_64(normalized_divisor.part.hi, - normalized_divisor.part.lo); - ACPI_SHIFT_RIGHT_64(normalized_dividend.part.hi, - normalized_dividend.part.lo); - - } while (normalized_divisor.part.hi != 0); - - /* Partial divide */ - - ACPI_DIV_64_BY_32(normalized_dividend.part.hi, - normalized_dividend.part.lo, - normalized_divisor.part.lo, - quotient.part.lo, partial1); - - /* - * The quotient is always 32 bits, and simply requires adjustment. - * The 64-bit remainder must be generated. - */ - partial1 = quotient.part.lo * divisor.part.hi; - partial2.full = - (acpi_integer) quotient.part.lo * divisor.part.lo; - partial3.full = (acpi_integer) partial2.part.hi + partial1; - - remainder.part.hi = partial3.part.lo; - remainder.part.lo = partial2.part.lo; - - if (partial3.part.hi == 0) { - if (partial3.part.lo >= dividend.part.hi) { - if (partial3.part.lo == dividend.part.hi) { - if (partial2.part.lo > dividend.part.lo) { - quotient.part.lo--; - remainder.full -= divisor.full; - } - } else { - quotient.part.lo--; - remainder.full -= divisor.full; - } - } - - remainder.full = remainder.full - dividend.full; - remainder.part.hi = (u32) - ((s32) remainder.part.hi); - remainder.part.lo = (u32) - ((s32) remainder.part.lo); - - if (remainder.part.lo) { - remainder.part.hi--; - } - } - } - - /* Return only what was requested */ - - if (out_quotient) { - *out_quotient = quotient.full; - } - if (out_remainder) { - *out_remainder = remainder.full; - } - - return_ACPI_STATUS(AE_OK); -} - -#else -/******************************************************************************* - * - * FUNCTION: acpi_ut_short_divide, acpi_ut_divide - * - * PARAMETERS: See function headers above - * - * DESCRIPTION: Native versions of the ut_divide functions. Use these if either - * 1) The target is a 64-bit platform and therefore 64-bit - * integer math is supported directly by the machine. - * 2) The target is a 32-bit or 16-bit platform, and the - * double-precision integer math library is available to - * perform the divide. - * - ******************************************************************************/ -acpi_status -acpi_ut_short_divide(acpi_integer in_dividend, - u32 divisor, - acpi_integer * out_quotient, u32 * out_remainder) -{ - - ACPI_FUNCTION_TRACE(ut_short_divide); - - /* Always check for a zero divisor */ - - if (divisor == 0) { - ACPI_ERROR((AE_INFO, "Divide by zero")); - return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); - } - - /* Return only what was requested */ - - if (out_quotient) { - *out_quotient = in_dividend / divisor; - } - if (out_remainder) { - *out_remainder = (u32) (in_dividend % divisor); - } - - return_ACPI_STATUS(AE_OK); -} - -acpi_status -acpi_ut_divide(acpi_integer in_dividend, - acpi_integer in_divisor, - acpi_integer * out_quotient, acpi_integer * out_remainder) -{ - ACPI_FUNCTION_TRACE(ut_divide); - - /* Always check for a zero divisor */ - - if (in_divisor == 0) { - ACPI_ERROR((AE_INFO, "Divide by zero")); - return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); - } - - /* Return only what was requested */ - - if (out_quotient) { - *out_quotient = in_dividend / in_divisor; - } - if (out_remainder) { - *out_remainder = in_dividend % in_divisor; - } - - return_ACPI_STATUS(AE_OK); -} - -#endif diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c deleted file mode 100644 index 8f8b407142ee..000000000000 --- a/drivers/acpi/utilities/utmisc.c +++ /dev/null @@ -1,1093 +0,0 @@ -/******************************************************************************* - * - * Module Name: utmisc - common utility procedures - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include - -#include -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utmisc") - -/******************************************************************************* - * - * FUNCTION: acpi_ut_validate_exception - * - * PARAMETERS: Status - The acpi_status code to be formatted - * - * RETURN: A string containing the exception text. NULL if exception is - * not valid. - * - * DESCRIPTION: This function validates and translates an ACPI exception into - * an ASCII string. - * - ******************************************************************************/ -const char *acpi_ut_validate_exception(acpi_status status) -{ - u32 sub_status; - const char *exception = NULL; - - ACPI_FUNCTION_ENTRY(); - - /* - * Status is composed of two parts, a "type" and an actual code - */ - sub_status = (status & ~AE_CODE_MASK); - - switch (status & AE_CODE_MASK) { - case AE_CODE_ENVIRONMENTAL: - - if (sub_status <= AE_CODE_ENV_MAX) { - exception = acpi_gbl_exception_names_env[sub_status]; - } - break; - - case AE_CODE_PROGRAMMER: - - if (sub_status <= AE_CODE_PGM_MAX) { - exception = acpi_gbl_exception_names_pgm[sub_status]; - } - break; - - case AE_CODE_ACPI_TABLES: - - if (sub_status <= AE_CODE_TBL_MAX) { - exception = acpi_gbl_exception_names_tbl[sub_status]; - } - break; - - case AE_CODE_AML: - - if (sub_status <= AE_CODE_AML_MAX) { - exception = acpi_gbl_exception_names_aml[sub_status]; - } - break; - - case AE_CODE_CONTROL: - - if (sub_status <= AE_CODE_CTRL_MAX) { - exception = acpi_gbl_exception_names_ctrl[sub_status]; - } - break; - - default: - break; - } - - return (ACPI_CAST_PTR(const char, exception)); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_is_aml_table - * - * PARAMETERS: Table - An ACPI table - * - * RETURN: TRUE if table contains executable AML; FALSE otherwise - * - * DESCRIPTION: Check ACPI Signature for a table that contains AML code. - * Currently, these are DSDT,SSDT,PSDT. All other table types are - * data tables that do not contain AML code. - * - ******************************************************************************/ - -u8 acpi_ut_is_aml_table(struct acpi_table_header *table) -{ - - /* These are the only tables that contain executable AML */ - - if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) || - ACPI_COMPARE_NAME(table->signature, ACPI_SIG_PSDT) || - ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) { - return (TRUE); - } - - return (FALSE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate_owner_id - * - * PARAMETERS: owner_id - Where the new owner ID is returned - * - * RETURN: Status - * - * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to - * track objects created by the table or method, to be deleted - * when the method exits or the table is unloaded. - * - ******************************************************************************/ - -acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) -{ - u32 i; - u32 j; - u32 k; - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_allocate_owner_id); - - /* Guard against multiple allocations of ID to the same location */ - - if (*owner_id) { - ACPI_ERROR((AE_INFO, "Owner ID [%2.2X] already exists", - *owner_id)); - return_ACPI_STATUS(AE_ALREADY_EXISTS); - } - - /* Mutex for the global ID mask */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Find a free owner ID, cycle through all possible IDs on repeated - * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have - * to be scanned twice. - */ - for (i = 0, j = acpi_gbl_last_owner_id_index; - i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { - if (j >= ACPI_NUM_OWNERID_MASKS) { - j = 0; /* Wraparound to start of mask array */ - } - - for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { - if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { - - /* There are no free IDs in this mask */ - - break; - } - - if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { - /* - * Found a free ID. The actual ID is the bit index plus one, - * making zero an invalid Owner ID. Save this as the last ID - * allocated and update the global ID mask. - */ - acpi_gbl_owner_id_mask[j] |= (1 << k); - - acpi_gbl_last_owner_id_index = (u8) j; - acpi_gbl_next_owner_id_offset = (u8) (k + 1); - - /* - * Construct encoded ID from the index and bit position - * - * Note: Last [j].k (bit 255) is never used and is marked - * permanently allocated (prevents +1 overflow) - */ - *owner_id = - (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); - - ACPI_DEBUG_PRINT((ACPI_DB_VALUES, - "Allocated OwnerId: %2.2X\n", - (unsigned int)*owner_id)); - goto exit; - } - } - - acpi_gbl_next_owner_id_offset = 0; - } - - /* - * All owner_ids have been allocated. This typically should - * not happen since the IDs are reused after deallocation. The IDs are - * allocated upon table load (one per table) and method execution, and - * they are released when a table is unloaded or a method completes - * execution. - * - * If this error happens, there may be very deep nesting of invoked control - * methods, or there may be a bug where the IDs are not released. - */ - status = AE_OWNER_ID_LIMIT; - ACPI_ERROR((AE_INFO, - "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); - - exit: - (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_release_owner_id - * - * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_iD - * - * RETURN: None. No error is returned because we are either exiting a - * control method or unloading a table. Either way, we would - * ignore any error anyway. - * - * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 - * - ******************************************************************************/ - -void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) -{ - acpi_owner_id owner_id = *owner_id_ptr; - acpi_status status; - u32 index; - u32 bit; - - ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); - - /* Always clear the input owner_id (zero is an invalid ID) */ - - *owner_id_ptr = 0; - - /* Zero is not a valid owner_iD */ - - if (owner_id == 0) { - ACPI_ERROR((AE_INFO, "Invalid OwnerId: %2.2X", owner_id)); - return_VOID; - } - - /* Mutex for the global ID mask */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); - if (ACPI_FAILURE(status)) { - return_VOID; - } - - /* Normalize the ID to zero */ - - owner_id--; - - /* Decode ID to index/offset pair */ - - index = ACPI_DIV_32(owner_id); - bit = 1 << ACPI_MOD_32(owner_id); - - /* Free the owner ID only if it is valid */ - - if (acpi_gbl_owner_id_mask[index] & bit) { - acpi_gbl_owner_id_mask[index] ^= bit; - } else { - ACPI_ERROR((AE_INFO, - "Release of non-allocated OwnerId: %2.2X", - owner_id + 1)); - } - - (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_strupr (strupr) - * - * PARAMETERS: src_string - The source string to convert - * - * RETURN: None - * - * DESCRIPTION: Convert string to uppercase - * - * NOTE: This is not a POSIX function, so it appears here, not in utclib.c - * - ******************************************************************************/ - -void acpi_ut_strupr(char *src_string) -{ - char *string; - - ACPI_FUNCTION_ENTRY(); - - if (!src_string) { - return; - } - - /* Walk entire string, uppercasing the letters */ - - for (string = src_string; *string; string++) { - *string = (char)ACPI_TOUPPER(*string); - } - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_print_string - * - * PARAMETERS: String - Null terminated ASCII string - * max_length - Maximum output length - * - * RETURN: None - * - * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape - * sequences. - * - ******************************************************************************/ - -void acpi_ut_print_string(char *string, u8 max_length) -{ - u32 i; - - if (!string) { - acpi_os_printf("<\"NULL STRING PTR\">"); - return; - } - - acpi_os_printf("\""); - for (i = 0; string[i] && (i < max_length); i++) { - - /* Escape sequences */ - - switch (string[i]) { - case 0x07: - acpi_os_printf("\\a"); /* BELL */ - break; - - case 0x08: - acpi_os_printf("\\b"); /* BACKSPACE */ - break; - - case 0x0C: - acpi_os_printf("\\f"); /* FORMFEED */ - break; - - case 0x0A: - acpi_os_printf("\\n"); /* LINEFEED */ - break; - - case 0x0D: - acpi_os_printf("\\r"); /* CARRIAGE RETURN */ - break; - - case 0x09: - acpi_os_printf("\\t"); /* HORIZONTAL TAB */ - break; - - case 0x0B: - acpi_os_printf("\\v"); /* VERTICAL TAB */ - break; - - case '\'': /* Single Quote */ - case '\"': /* Double Quote */ - case '\\': /* Backslash */ - acpi_os_printf("\\%c", (int)string[i]); - break; - - default: - - /* Check for printable character or hex escape */ - - if (ACPI_IS_PRINT(string[i])) { - /* This is a normal character */ - - acpi_os_printf("%c", (int)string[i]); - } else { - /* All others will be Hex escapes */ - - acpi_os_printf("\\x%2.2X", (s32) string[i]); - } - break; - } - } - acpi_os_printf("\""); - - if (i == max_length && string[i]) { - acpi_os_printf("..."); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_dword_byte_swap - * - * PARAMETERS: Value - Value to be converted - * - * RETURN: u32 integer with bytes swapped - * - * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes) - * - ******************************************************************************/ - -u32 acpi_ut_dword_byte_swap(u32 value) -{ - union { - u32 value; - u8 bytes[4]; - } out; - union { - u32 value; - u8 bytes[4]; - } in; - - ACPI_FUNCTION_ENTRY(); - - in.value = value; - - out.bytes[0] = in.bytes[3]; - out.bytes[1] = in.bytes[2]; - out.bytes[2] = in.bytes[1]; - out.bytes[3] = in.bytes[0]; - - return (out.value); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_set_integer_width - * - * PARAMETERS: Revision From DSDT header - * - * RETURN: None - * - * DESCRIPTION: Set the global integer bit width based upon the revision - * of the DSDT. For Revision 1 and 0, Integers are 32 bits. - * For Revision 2 and above, Integers are 64 bits. Yes, this - * makes a difference. - * - ******************************************************************************/ - -void acpi_ut_set_integer_width(u8 revision) -{ - - if (revision < 2) { - - /* 32-bit case */ - - acpi_gbl_integer_bit_width = 32; - acpi_gbl_integer_nybble_width = 8; - acpi_gbl_integer_byte_width = 4; - } else { - /* 64-bit case (ACPI 2.0+) */ - - acpi_gbl_integer_bit_width = 64; - acpi_gbl_integer_nybble_width = 16; - acpi_gbl_integer_byte_width = 8; - } -} - -#ifdef ACPI_DEBUG_OUTPUT -/******************************************************************************* - * - * FUNCTION: acpi_ut_display_init_pathname - * - * PARAMETERS: Type - Object type of the node - * obj_handle - Handle whose pathname will be displayed - * Path - Additional path string to be appended. - * (NULL if no extra path) - * - * RETURN: acpi_status - * - * DESCRIPTION: Display full pathname of an object, DEBUG ONLY - * - ******************************************************************************/ - -void -acpi_ut_display_init_pathname(u8 type, - struct acpi_namespace_node *obj_handle, - char *path) -{ - acpi_status status; - struct acpi_buffer buffer; - - ACPI_FUNCTION_ENTRY(); - - /* Only print the path if the appropriate debug level is enabled */ - - if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { - return; - } - - /* Get the full pathname to the node */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_ns_handle_to_pathname(obj_handle, &buffer); - if (ACPI_FAILURE(status)) { - return; - } - - /* Print what we're doing */ - - switch (type) { - case ACPI_TYPE_METHOD: - acpi_os_printf("Executing "); - break; - - default: - acpi_os_printf("Initializing "); - break; - } - - /* Print the object type and pathname */ - - acpi_os_printf("%-12s %s", - acpi_ut_get_type_name(type), (char *)buffer.pointer); - - /* Extra path is used to append names like _STA, _INI, etc. */ - - if (path) { - acpi_os_printf(".%s", path); - } - acpi_os_printf("\n"); - - ACPI_FREE(buffer.pointer); -} -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ut_valid_acpi_char - * - * PARAMETERS: Char - The character to be examined - * Position - Byte position (0-3) - * - * RETURN: TRUE if the character is valid, FALSE otherwise - * - * DESCRIPTION: Check for a valid ACPI character. Must be one of: - * 1) Upper case alpha - * 2) numeric - * 3) underscore - * - * We allow a '!' as the last character because of the ASF! table - * - ******************************************************************************/ - -u8 acpi_ut_valid_acpi_char(char character, u32 position) -{ - - if (!((character >= 'A' && character <= 'Z') || - (character >= '0' && character <= '9') || (character == '_'))) { - - /* Allow a '!' in the last position */ - - if (character == '!' && position == 3) { - return (TRUE); - } - - return (FALSE); - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_valid_acpi_name - * - * PARAMETERS: Name - The name to be examined - * - * RETURN: TRUE if the name is valid, FALSE otherwise - * - * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: - * 1) Upper case alpha - * 2) numeric - * 3) underscore - * - ******************************************************************************/ - -u8 acpi_ut_valid_acpi_name(u32 name) -{ - u32 i; - - ACPI_FUNCTION_ENTRY(); - - for (i = 0; i < ACPI_NAME_SIZE; i++) { - if (!acpi_ut_valid_acpi_char - ((ACPI_CAST_PTR(char, &name))[i], i)) { - return (FALSE); - } - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_repair_name - * - * PARAMETERS: Name - The ACPI name to be repaired - * - * RETURN: Repaired version of the name - * - * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and - * return the new name. - * - ******************************************************************************/ - -acpi_name acpi_ut_repair_name(char *name) -{ - u32 i; - char new_name[ACPI_NAME_SIZE]; - - for (i = 0; i < ACPI_NAME_SIZE; i++) { - new_name[i] = name[i]; - - /* - * Replace a bad character with something printable, yet technically - * still invalid. This prevents any collisions with existing "good" - * names in the namespace. - */ - if (!acpi_ut_valid_acpi_char(name[i], i)) { - new_name[i] = '*'; - } - } - - return (*(u32 *) new_name); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_strtoul64 - * - * PARAMETERS: String - Null terminated string - * Base - Radix of the string: 16 or ACPI_ANY_BASE; - * ACPI_ANY_BASE means 'in behalf of to_integer' - * ret_integer - Where the converted integer is returned - * - * RETURN: Status and Converted value - * - * DESCRIPTION: Convert a string into an unsigned value. Performs either a - * 32-bit or 64-bit conversion, depending on the current mode - * of the interpreter. - * NOTE: Does not support Octal strings, not needed. - * - ******************************************************************************/ - -acpi_status -acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) -{ - u32 this_digit = 0; - acpi_integer return_value = 0; - acpi_integer quotient; - acpi_integer dividend; - u32 to_integer_op = (base == ACPI_ANY_BASE); - u32 mode32 = (acpi_gbl_integer_byte_width == 4); - u8 valid_digits = 0; - u8 sign_of0x = 0; - u8 term = 0; - - ACPI_FUNCTION_TRACE_STR(ut_stroul64, string); - - switch (base) { - case ACPI_ANY_BASE: - case 16: - break; - - default: - /* Invalid Base */ - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (!string) { - goto error_exit; - } - - /* Skip over any white space in the buffer */ - - while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { - string++; - } - - if (to_integer_op) { - /* - * Base equal to ACPI_ANY_BASE means 'to_integer operation case'. - * We need to determine if it is decimal or hexadecimal. - */ - if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { - sign_of0x = 1; - base = 16; - - /* Skip over the leading '0x' */ - string += 2; - } else { - base = 10; - } - } - - /* Any string left? Check that '0x' is not followed by white space. */ - - if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { - if (to_integer_op) { - goto error_exit; - } else { - goto all_done; - } - } - - /* - * Perform a 32-bit or 64-bit conversion, depending upon the current - * execution mode of the interpreter - */ - dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; - - /* Main loop: convert the string to a 32- or 64-bit integer */ - - while (*string) { - if (ACPI_IS_DIGIT(*string)) { - - /* Convert ASCII 0-9 to Decimal value */ - - this_digit = ((u8) * string) - '0'; - } else if (base == 10) { - - /* Digit is out of range; possible in to_integer case only */ - - term = 1; - } else { - this_digit = (u8) ACPI_TOUPPER(*string); - if (ACPI_IS_XDIGIT((char)this_digit)) { - - /* Convert ASCII Hex char to value */ - - this_digit = this_digit - 'A' + 10; - } else { - term = 1; - } - } - - if (term) { - if (to_integer_op) { - goto error_exit; - } else { - break; - } - } else if ((valid_digits == 0) && (this_digit == 0) - && !sign_of0x) { - - /* Skip zeros */ - string++; - continue; - } - - valid_digits++; - - if (sign_of0x && ((valid_digits > 16) - || ((valid_digits > 8) && mode32))) { - /* - * This is to_integer operation case. - * No any restrictions for string-to-integer conversion, - * see ACPI spec. - */ - goto error_exit; - } - - /* Divide the digit into the correct position */ - - (void) - acpi_ut_short_divide((dividend - (acpi_integer) this_digit), - base, "ient, NULL); - - if (return_value > quotient) { - if (to_integer_op) { - goto error_exit; - } else { - break; - } - } - - return_value *= base; - return_value += this_digit; - string++; - } - - /* All done, normal exit */ - - all_done: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(return_value))); - - *ret_integer = return_value; - return_ACPI_STATUS(AE_OK); - - error_exit: - /* Base was set/validated above */ - - if (base == 10) { - return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); - } else { - return_ACPI_STATUS(AE_BAD_HEX_CONSTANT); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_update_state_and_push - * - * PARAMETERS: Object - Object to be added to the new state - * Action - Increment/Decrement - * state_list - List the state will be added to - * - * RETURN: Status - * - * DESCRIPTION: Create a new state and push it - * - ******************************************************************************/ - -acpi_status -acpi_ut_create_update_state_and_push(union acpi_operand_object *object, - u16 action, - union acpi_generic_state **state_list) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_ENTRY(); - - /* Ignore null objects; these are expected */ - - if (!object) { - return (AE_OK); - } - - state = acpi_ut_create_update_state(object, action); - if (!state) { - return (AE_NO_MEMORY); - } - - acpi_ut_push_generic_state(state_list, state); - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_walk_package_tree - * - * PARAMETERS: source_object - The package to walk - * target_object - Target object (if package is being copied) - * walk_callback - Called once for each package element - * Context - Passed to the callback function - * - * RETURN: Status - * - * DESCRIPTION: Walk through a package - * - ******************************************************************************/ - -acpi_status -acpi_ut_walk_package_tree(union acpi_operand_object * source_object, - void *target_object, - acpi_pkg_callback walk_callback, void *context) -{ - acpi_status status = AE_OK; - union acpi_generic_state *state_list = NULL; - union acpi_generic_state *state; - u32 this_index; - union acpi_operand_object *this_source_obj; - - ACPI_FUNCTION_TRACE(ut_walk_package_tree); - - state = acpi_ut_create_pkg_state(source_object, target_object, 0); - if (!state) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - while (state) { - - /* Get one element of the package */ - - this_index = state->pkg.index; - this_source_obj = (union acpi_operand_object *) - state->pkg.source_object->package.elements[this_index]; - - /* - * Check for: - * 1) An uninitialized package element. It is completely - * legal to declare a package and leave it uninitialized - * 2) Not an internal object - can be a namespace node instead - * 3) Any type other than a package. Packages are handled in else - * case below. - */ - if ((!this_source_obj) || - (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) != - ACPI_DESC_TYPE_OPERAND) - || (ACPI_GET_OBJECT_TYPE(this_source_obj) != - ACPI_TYPE_PACKAGE)) { - status = - walk_callback(ACPI_COPY_TYPE_SIMPLE, - this_source_obj, state, context); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - state->pkg.index++; - while (state->pkg.index >= - state->pkg.source_object->package.count) { - /* - * We've handled all of the objects at this level, This means - * that we have just completed a package. That package may - * have contained one or more packages itself. - * - * Delete this state and pop the previous state (package). - */ - acpi_ut_delete_generic_state(state); - state = acpi_ut_pop_generic_state(&state_list); - - /* Finished when there are no more states */ - - if (!state) { - /* - * We have handled all of the objects in the top level - * package just add the length of the package objects - * and exit - */ - return_ACPI_STATUS(AE_OK); - } - - /* - * Go back up a level and move the index past the just - * completed package object. - */ - state->pkg.index++; - } - } else { - /* This is a subobject of type package */ - - status = - walk_callback(ACPI_COPY_TYPE_PACKAGE, - this_source_obj, state, context); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Push the current state and create a new one - * The callback above returned a new target package object. - */ - acpi_ut_push_generic_state(&state_list, state); - state = acpi_ut_create_pkg_state(this_source_obj, - state->pkg. - this_target_obj, 0); - if (!state) { - - /* Free any stacked Update State objects */ - - while (state_list) { - state = - acpi_ut_pop_generic_state - (&state_list); - acpi_ut_delete_generic_state(state); - } - return_ACPI_STATUS(AE_NO_MEMORY); - } - } - } - - /* We should never get here */ - - return_ACPI_STATUS(AE_AML_INTERNAL); -} - -/******************************************************************************* - * - * FUNCTION: acpi_error, acpi_exception, acpi_warning, acpi_info - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * Format - Printf format string + additional args - * - * RETURN: None - * - * DESCRIPTION: Print message with module/line/version info - * - ******************************************************************************/ - -void ACPI_INTERNAL_VAR_XFACE -acpi_error(const char *module_name, u32 line_number, const char *format, ...) -{ - va_list args; - - acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); - - va_start(args, format); - acpi_os_vprintf(format, args); - acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); - va_end(args); -} - -void ACPI_INTERNAL_VAR_XFACE -acpi_exception(const char *module_name, - u32 line_number, acpi_status status, const char *format, ...) -{ - va_list args; - - acpi_os_printf("ACPI Exception (%s-%04d): %s, ", module_name, - line_number, acpi_format_exception(status)); - - va_start(args, format); - acpi_os_vprintf(format, args); - acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); - va_end(args); -} - -void ACPI_INTERNAL_VAR_XFACE -acpi_warning(const char *module_name, u32 line_number, const char *format, ...) -{ - va_list args; - - acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number); - - va_start(args, format); - acpi_os_vprintf(format, args); - acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); - va_end(args); -} - -void ACPI_INTERNAL_VAR_XFACE -acpi_info(const char *module_name, u32 line_number, const char *format, ...) -{ - va_list args; - - /* - * Removed module_name, line_number, and acpica version, not needed - * for info output - */ - acpi_os_printf("ACPI: "); - - va_start(args, format); - acpi_os_vprintf(format, args); - acpi_os_printf("\n"); - va_end(args); -} - -ACPI_EXPORT_SYMBOL(acpi_error) -ACPI_EXPORT_SYMBOL(acpi_exception) -ACPI_EXPORT_SYMBOL(acpi_warning) -ACPI_EXPORT_SYMBOL(acpi_info) diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c deleted file mode 100644 index 7b48ba3f3f8a..000000000000 --- a/drivers/acpi/utilities/utmutex.c +++ /dev/null @@ -1,342 +0,0 @@ -/******************************************************************************* - * - * Module Name: utmutex - local mutex support - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utmutex") - -/* Local prototypes */ -static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id); - -static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id); - -/******************************************************************************* - * - * FUNCTION: acpi_ut_mutex_initialize - * - * PARAMETERS: None. - * - * RETURN: Status - * - * DESCRIPTION: Create the system mutex objects. - * - ******************************************************************************/ - -acpi_status acpi_ut_mutex_initialize(void) -{ - u32 i; - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_mutex_initialize); - - /* - * Create each of the predefined mutex objects - */ - for (i = 0; i < ACPI_NUM_MUTEX; i++) { - status = acpi_ut_create_mutex(i); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* Create the spinlocks for use at interrupt level */ - - spin_lock_init(acpi_gbl_gpe_lock); - spin_lock_init(acpi_gbl_hardware_lock); - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_mutex_terminate - * - * PARAMETERS: None. - * - * RETURN: None. - * - * DESCRIPTION: Delete all of the system mutex objects. - * - ******************************************************************************/ - -void acpi_ut_mutex_terminate(void) -{ - u32 i; - - ACPI_FUNCTION_TRACE(ut_mutex_terminate); - - /* - * Delete each predefined mutex object - */ - for (i = 0; i < ACPI_NUM_MUTEX; i++) { - (void)acpi_ut_delete_mutex(i); - } - - /* Delete the spinlocks */ - - acpi_os_delete_lock(acpi_gbl_gpe_lock); - acpi_os_delete_lock(acpi_gbl_hardware_lock); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_mutex - * - * PARAMETERS: mutex_iD - ID of the mutex to be created - * - * RETURN: Status - * - * DESCRIPTION: Create a mutex object. - * - ******************************************************************************/ - -static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id); - - if (mutex_id > ACPI_MAX_MUTEX) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (!acpi_gbl_mutex_info[mutex_id].mutex) { - status = - acpi_os_create_mutex(&acpi_gbl_mutex_info[mutex_id].mutex); - acpi_gbl_mutex_info[mutex_id].thread_id = - ACPI_MUTEX_NOT_ACQUIRED; - acpi_gbl_mutex_info[mutex_id].use_count = 0; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_delete_mutex - * - * PARAMETERS: mutex_iD - ID of the mutex to be deleted - * - * RETURN: Status - * - * DESCRIPTION: Delete a mutex object. - * - ******************************************************************************/ - -static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id) -{ - - ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id); - - if (mutex_id > ACPI_MAX_MUTEX) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - acpi_os_delete_mutex(acpi_gbl_mutex_info[mutex_id].mutex); - - acpi_gbl_mutex_info[mutex_id].mutex = NULL; - acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_acquire_mutex - * - * PARAMETERS: mutex_iD - ID of the mutex to be acquired - * - * RETURN: Status - * - * DESCRIPTION: Acquire a mutex object. - * - ******************************************************************************/ - -acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) -{ - acpi_status status; - acpi_thread_id this_thread_id; - - ACPI_FUNCTION_NAME(ut_acquire_mutex); - - if (mutex_id > ACPI_MAX_MUTEX) { - return (AE_BAD_PARAMETER); - } - - this_thread_id = acpi_os_get_thread_id(); - -#ifdef ACPI_MUTEX_DEBUG - { - u32 i; - /* - * Mutex debug code, for internal debugging only. - * - * Deadlock prevention. Check if this thread owns any mutexes of value - * greater than or equal to this one. If so, the thread has violated - * the mutex ordering rule. This indicates a coding error somewhere in - * the ACPI subsystem code. - */ - for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { - if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { - if (i == mutex_id) { - ACPI_ERROR((AE_INFO, - "Mutex [%s] already acquired by this thread [%X]", - acpi_ut_get_mutex_name - (mutex_id), - this_thread_id)); - - return (AE_ALREADY_ACQUIRED); - } - - ACPI_ERROR((AE_INFO, - "Invalid acquire order: Thread %X owns [%s], wants [%s]", - this_thread_id, - acpi_ut_get_mutex_name(i), - acpi_ut_get_mutex_name(mutex_id))); - - return (AE_ACQUIRE_DEADLOCK); - } - } - } -#endif - - ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, - "Thread %lX attempting to acquire Mutex [%s]\n", - (unsigned long)this_thread_id, - acpi_ut_get_mutex_name(mutex_id))); - - status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex, - ACPI_WAIT_FOREVER); - if (ACPI_SUCCESS(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, - "Thread %lX acquired Mutex [%s]\n", - (unsigned long)this_thread_id, - acpi_ut_get_mutex_name(mutex_id))); - - acpi_gbl_mutex_info[mutex_id].use_count++; - acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id; - } else { - ACPI_EXCEPTION((AE_INFO, status, - "Thread %lX could not acquire Mutex [%X]", - (unsigned long)this_thread_id, mutex_id)); - } - - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_release_mutex - * - * PARAMETERS: mutex_iD - ID of the mutex to be released - * - * RETURN: Status - * - * DESCRIPTION: Release a mutex object. - * - ******************************************************************************/ - -acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) -{ - acpi_thread_id this_thread_id; - - ACPI_FUNCTION_NAME(ut_release_mutex); - - this_thread_id = acpi_os_get_thread_id(); - ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, - "Thread %lX releasing Mutex [%s]\n", - (unsigned long)this_thread_id, - acpi_ut_get_mutex_name(mutex_id))); - - if (mutex_id > ACPI_MAX_MUTEX) { - return (AE_BAD_PARAMETER); - } - - /* - * Mutex must be acquired in order to release it! - */ - if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) { - ACPI_ERROR((AE_INFO, - "Mutex [%X] is not acquired, cannot release", - mutex_id)); - - return (AE_NOT_ACQUIRED); - } -#ifdef ACPI_MUTEX_DEBUG - { - u32 i; - /* - * Mutex debug code, for internal debugging only. - * - * Deadlock prevention. Check if this thread owns any mutexes of value - * greater than this one. If so, the thread has violated the mutex - * ordering rule. This indicates a coding error somewhere in - * the ACPI subsystem code. - */ - for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { - if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { - if (i == mutex_id) { - continue; - } - - ACPI_ERROR((AE_INFO, - "Invalid release order: owns [%s], releasing [%s]", - acpi_ut_get_mutex_name(i), - acpi_ut_get_mutex_name(mutex_id))); - - return (AE_RELEASE_DEADLOCK); - } - } - } -#endif - - /* Mark unlocked FIRST */ - - acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; - - acpi_os_release_mutex(acpi_gbl_mutex_info[mutex_id].mutex); - return (AE_OK); -} diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c deleted file mode 100644 index 964b23c11610..000000000000 --- a/drivers/acpi/utilities/utobject.c +++ /dev/null @@ -1,677 +0,0 @@ -/****************************************************************************** - * - * Module Name: utobject - ACPI object create/delete/size/cache routines - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utobject") - -/* Local prototypes */ -static acpi_status -acpi_ut_get_simple_object_size(union acpi_operand_object *obj, - acpi_size * obj_length); - -static acpi_status -acpi_ut_get_package_object_size(union acpi_operand_object *obj, - acpi_size * obj_length); - -static acpi_status -acpi_ut_get_element_length(u8 object_type, - union acpi_operand_object *source_object, - union acpi_generic_state *state, void *context); - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_internal_object_dbg - * - * PARAMETERS: module_name - Source file name of caller - * line_number - Line number of caller - * component_id - Component type of caller - * Type - ACPI Type of the new object - * - * RETURN: A new internal object, null on failure - * - * DESCRIPTION: Create and initialize a new internal object. - * - * NOTE: We always allocate the worst-case object descriptor because - * these objects are cached, and we want them to be - * one-size-satisifies-any-request. This in itself may not be - * the most memory efficient, but the efficiency of the object - * cache should more than make up for this! - * - ******************************************************************************/ - -union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char - *module_name, - u32 line_number, - u32 component_id, - acpi_object_type - type) -{ - union acpi_operand_object *object; - union acpi_operand_object *second_object; - - ACPI_FUNCTION_TRACE_STR(ut_create_internal_object_dbg, - acpi_ut_get_type_name(type)); - - /* Allocate the raw object descriptor */ - - object = - acpi_ut_allocate_object_desc_dbg(module_name, line_number, - component_id); - if (!object) { - return_PTR(NULL); - } - - switch (type) { - case ACPI_TYPE_REGION: - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - - /* These types require a secondary object */ - - second_object = acpi_ut_allocate_object_desc_dbg(module_name, - line_number, - component_id); - if (!second_object) { - acpi_ut_delete_object_desc(object); - return_PTR(NULL); - } - - second_object->common.type = ACPI_TYPE_LOCAL_EXTRA; - second_object->common.reference_count = 1; - - /* Link the second object to the first */ - - object->common.next_object = second_object; - break; - - default: - /* All others have no secondary object */ - break; - } - - /* Save the object type in the object descriptor */ - - object->common.type = (u8) type; - - /* Init the reference count */ - - object->common.reference_count = 1; - - /* Any per-type initialization should go here */ - - return_PTR(object); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_package_object - * - * PARAMETERS: Count - Number of package elements - * - * RETURN: Pointer to a new Package object, null on failure - * - * DESCRIPTION: Create a fully initialized package object - * - ******************************************************************************/ - -union acpi_operand_object *acpi_ut_create_package_object(u32 count) -{ - union acpi_operand_object *package_desc; - union acpi_operand_object **package_elements; - - ACPI_FUNCTION_TRACE_U32(ut_create_package_object, count); - - /* Create a new Package object */ - - package_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE); - if (!package_desc) { - return_PTR(NULL); - } - - /* - * Create the element array. Count+1 allows the array to be null - * terminated. - */ - package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size) count + - 1) * sizeof(void *)); - if (!package_elements) { - acpi_ut_remove_reference(package_desc); - return_PTR(NULL); - } - - package_desc->package.count = count; - package_desc->package.elements = package_elements; - return_PTR(package_desc); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_buffer_object - * - * PARAMETERS: buffer_size - Size of buffer to be created - * - * RETURN: Pointer to a new Buffer object, null on failure - * - * DESCRIPTION: Create a fully initialized buffer object - * - ******************************************************************************/ - -union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size) -{ - union acpi_operand_object *buffer_desc; - u8 *buffer = NULL; - - ACPI_FUNCTION_TRACE_U32(ut_create_buffer_object, buffer_size); - - /* Create a new Buffer object */ - - buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); - if (!buffer_desc) { - return_PTR(NULL); - } - - /* Create an actual buffer only if size > 0 */ - - if (buffer_size > 0) { - - /* Allocate the actual buffer */ - - buffer = ACPI_ALLOCATE_ZEROED(buffer_size); - if (!buffer) { - ACPI_ERROR((AE_INFO, "Could not allocate size %X", - (u32) buffer_size)); - acpi_ut_remove_reference(buffer_desc); - return_PTR(NULL); - } - } - - /* Complete buffer object initialization */ - - buffer_desc->buffer.flags |= AOPOBJ_DATA_VALID; - buffer_desc->buffer.pointer = buffer; - buffer_desc->buffer.length = (u32) buffer_size; - - /* Return the new buffer descriptor */ - - return_PTR(buffer_desc); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_string_object - * - * PARAMETERS: string_size - Size of string to be created. Does not - * include NULL terminator, this is added - * automatically. - * - * RETURN: Pointer to a new String object - * - * DESCRIPTION: Create a fully initialized string object - * - ******************************************************************************/ - -union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size) -{ - union acpi_operand_object *string_desc; - char *string; - - ACPI_FUNCTION_TRACE_U32(ut_create_string_object, string_size); - - /* Create a new String object */ - - string_desc = acpi_ut_create_internal_object(ACPI_TYPE_STRING); - if (!string_desc) { - return_PTR(NULL); - } - - /* - * Allocate the actual string buffer -- (Size + 1) for NULL terminator. - * NOTE: Zero-length strings are NULL terminated - */ - string = ACPI_ALLOCATE_ZEROED(string_size + 1); - if (!string) { - ACPI_ERROR((AE_INFO, "Could not allocate size %X", - (u32) string_size)); - acpi_ut_remove_reference(string_desc); - return_PTR(NULL); - } - - /* Complete string object initialization */ - - string_desc->string.pointer = string; - string_desc->string.length = (u32) string_size; - - /* Return the new string descriptor */ - - return_PTR(string_desc); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_valid_internal_object - * - * PARAMETERS: Object - Object to be validated - * - * RETURN: TRUE if object is valid, FALSE otherwise - * - * DESCRIPTION: Validate a pointer to be an union acpi_operand_object - * - ******************************************************************************/ - -u8 acpi_ut_valid_internal_object(void *object) -{ - - ACPI_FUNCTION_NAME(ut_valid_internal_object); - - /* Check for a null pointer */ - - if (!object) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Null Object Ptr\n")); - return (FALSE); - } - - /* Check the descriptor type field */ - - switch (ACPI_GET_DESCRIPTOR_TYPE(object)) { - case ACPI_DESC_TYPE_OPERAND: - - /* The object appears to be a valid union acpi_operand_object */ - - return (TRUE); - - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "%p is not not an ACPI operand obj [%s]\n", - object, acpi_ut_get_descriptor_name(object))); - break; - } - - return (FALSE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate_object_desc_dbg - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * component_id - Caller's component ID (for error output) - * - * RETURN: Pointer to newly allocated object descriptor. Null on error - * - * DESCRIPTION: Allocate a new object descriptor. Gracefully handle - * error conditions. - * - ******************************************************************************/ - -void *acpi_ut_allocate_object_desc_dbg(const char *module_name, - u32 line_number, u32 component_id) -{ - union acpi_operand_object *object; - - ACPI_FUNCTION_TRACE(ut_allocate_object_desc_dbg); - - object = acpi_os_acquire_object(acpi_gbl_operand_cache); - if (!object) { - ACPI_ERROR((module_name, line_number, - "Could not allocate an object descriptor")); - - return_PTR(NULL); - } - - /* Mark the descriptor type */ - - memset(object, 0, sizeof(union acpi_operand_object)); - ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND); - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p Size %X\n", - object, (u32) sizeof(union acpi_operand_object))); - - return_PTR(object); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_delete_object_desc - * - * PARAMETERS: Object - An Acpi internal object to be deleted - * - * RETURN: None. - * - * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache - * - ******************************************************************************/ - -void acpi_ut_delete_object_desc(union acpi_operand_object *object) -{ - ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object); - - /* Object must be an union acpi_operand_object */ - - if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { - ACPI_ERROR((AE_INFO, - "%p is not an ACPI Operand object [%s]", object, - acpi_ut_get_descriptor_name(object))); - return_VOID; - } - - (void)acpi_os_release_object(acpi_gbl_operand_cache, object); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_simple_object_size - * - * PARAMETERS: internal_object - An ACPI operand object - * obj_length - Where the length is returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to determine the space required to - * contain a simple object for return to an external user. - * - * The length includes the object structure plus any additional - * needed space. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, - acpi_size * obj_length) -{ - acpi_size length; - acpi_size size; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object); - - /* - * Handle a null object (Could be a uninitialized package - * element -- which is legal) - */ - if (!internal_object) { - *obj_length = sizeof(union acpi_object); - return_ACPI_STATUS(AE_OK); - } - - /* Start with the length of the Acpi object */ - - length = sizeof(union acpi_object); - - if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) { - - /* Object is a named object (reference), just return the length */ - - *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); - return_ACPI_STATUS(status); - } - - /* - * The final length depends on the object type - * Strings and Buffers are packed right up against the parent object and - * must be accessed bytewise or there may be alignment problems on - * certain processors - */ - switch (ACPI_GET_OBJECT_TYPE(internal_object)) { - case ACPI_TYPE_STRING: - - length += (acpi_size) internal_object->string.length + 1; - break; - - case ACPI_TYPE_BUFFER: - - length += (acpi_size) internal_object->buffer.length; - break; - - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_POWER: - - /* No extra data for these types */ - - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - - switch (internal_object->reference.class) { - case ACPI_REFCLASS_NAME: - - /* - * Get the actual length of the full pathname to this object. - * The reference will be converted to the pathname to the object - */ - size = - acpi_ns_get_pathname_length(internal_object-> - reference.node); - if (!size) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - length += ACPI_ROUND_UP_TO_NATIVE_WORD(size); - break; - - default: - - /* - * No other reference opcodes are supported. - * Notably, Locals and Args are not supported, but this may be - * required eventually. - */ - ACPI_ERROR((AE_INFO, - "Cannot convert to external object - " - "unsupported Reference Class [%s] %X in object %p", - acpi_ut_get_reference_name(internal_object), - internal_object->reference.class, - internal_object)); - status = AE_TYPE; - break; - } - break; - - default: - - ACPI_ERROR((AE_INFO, "Cannot convert to external object - " - "unsupported type [%s] %X in object %p", - acpi_ut_get_object_type_name(internal_object), - ACPI_GET_OBJECT_TYPE(internal_object), - internal_object)); - status = AE_TYPE; - break; - } - - /* - * Account for the space required by the object rounded up to the next - * multiple of the machine word size. This keeps each object aligned - * on a machine word boundary. (preventing alignment faults on some - * machines.) - */ - *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_element_length - * - * PARAMETERS: acpi_pkg_callback - * - * RETURN: Status - * - * DESCRIPTION: Get the length of one package element. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_get_element_length(u8 object_type, - union acpi_operand_object *source_object, - union acpi_generic_state *state, void *context) -{ - acpi_status status = AE_OK; - struct acpi_pkg_info *info = (struct acpi_pkg_info *)context; - acpi_size object_space; - - switch (object_type) { - case ACPI_COPY_TYPE_SIMPLE: - - /* - * Simple object - just get the size (Null object/entry is handled - * here also) and sum it into the running package length - */ - status = - acpi_ut_get_simple_object_size(source_object, - &object_space); - if (ACPI_FAILURE(status)) { - return (status); - } - - info->length += object_space; - break; - - case ACPI_COPY_TYPE_PACKAGE: - - /* Package object - nothing much to do here, let the walk handle it */ - - info->num_packages++; - state->pkg.this_target_obj = NULL; - break; - - default: - - /* No other types allowed */ - - return (AE_BAD_PARAMETER); - } - - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_package_object_size - * - * PARAMETERS: internal_object - An ACPI internal object - * obj_length - Where the length is returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to determine the space required to - * contain a package object for return to an external user. - * - * This is moderately complex since a package contains other - * objects including packages. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_get_package_object_size(union acpi_operand_object *internal_object, - acpi_size * obj_length) -{ - acpi_status status; - struct acpi_pkg_info info; - - ACPI_FUNCTION_TRACE_PTR(ut_get_package_object_size, internal_object); - - info.length = 0; - info.object_space = 0; - info.num_packages = 1; - - status = acpi_ut_walk_package_tree(internal_object, NULL, - acpi_ut_get_element_length, &info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * We have handled all of the objects in all levels of the package. - * just add the length of the package objects themselves. - * Round up to the next machine word. - */ - info.length += ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)) * - (acpi_size) info.num_packages; - - /* Return the total package length */ - - *obj_length = info.length; - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_object_size - * - * PARAMETERS: internal_object - An ACPI internal object - * obj_length - Where the length will be returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to determine the space required to - * contain an object for return to an API user. - * - ******************************************************************************/ - -acpi_status -acpi_ut_get_object_size(union acpi_operand_object *internal_object, - acpi_size * obj_length) -{ - acpi_status status; - - ACPI_FUNCTION_ENTRY(); - - if ((ACPI_GET_DESCRIPTOR_TYPE(internal_object) == - ACPI_DESC_TYPE_OPERAND) - && (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE)) { - status = - acpi_ut_get_package_object_size(internal_object, - obj_length); - } else { - status = - acpi_ut_get_simple_object_size(internal_object, obj_length); - } - - return (status); -} diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c deleted file mode 100644 index 0755c5cdbe18..000000000000 --- a/drivers/acpi/utilities/utresrc.c +++ /dev/null @@ -1,616 +0,0 @@ -/******************************************************************************* - * - * Module Name: utresrc - Resource management utilities - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utresrc") -#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) -/* - * Strings used to decode resource descriptors. - * Used by both the disasssembler and the debugger resource dump routines - */ -const char *acpi_gbl_bm_decode[] = { - "NotBusMaster", - "BusMaster" -}; - -const char *acpi_gbl_config_decode[] = { - "0 - Good Configuration", - "1 - Acceptable Configuration", - "2 - Suboptimal Configuration", - "3 - ***Invalid Configuration***", -}; - -const char *acpi_gbl_consume_decode[] = { - "ResourceProducer", - "ResourceConsumer" -}; - -const char *acpi_gbl_dec_decode[] = { - "PosDecode", - "SubDecode" -}; - -const char *acpi_gbl_he_decode[] = { - "Level", - "Edge" -}; - -const char *acpi_gbl_io_decode[] = { - "Decode10", - "Decode16" -}; - -const char *acpi_gbl_ll_decode[] = { - "ActiveHigh", - "ActiveLow" -}; - -const char *acpi_gbl_max_decode[] = { - "MaxNotFixed", - "MaxFixed" -}; - -const char *acpi_gbl_mem_decode[] = { - "NonCacheable", - "Cacheable", - "WriteCombining", - "Prefetchable" -}; - -const char *acpi_gbl_min_decode[] = { - "MinNotFixed", - "MinFixed" -}; - -const char *acpi_gbl_mtp_decode[] = { - "AddressRangeMemory", - "AddressRangeReserved", - "AddressRangeACPI", - "AddressRangeNVS" -}; - -const char *acpi_gbl_rng_decode[] = { - "InvalidRanges", - "NonISAOnlyRanges", - "ISAOnlyRanges", - "EntireRange" -}; - -const char *acpi_gbl_rw_decode[] = { - "ReadOnly", - "ReadWrite" -}; - -const char *acpi_gbl_shr_decode[] = { - "Exclusive", - "Shared" -}; - -const char *acpi_gbl_siz_decode[] = { - "Transfer8", - "Transfer8_16", - "Transfer16", - "InvalidSize" -}; - -const char *acpi_gbl_trs_decode[] = { - "DenseTranslation", - "SparseTranslation" -}; - -const char *acpi_gbl_ttp_decode[] = { - "TypeStatic", - "TypeTranslation" -}; - -const char *acpi_gbl_typ_decode[] = { - "Compatibility", - "TypeA", - "TypeB", - "TypeF" -}; - -#endif - -/* - * Base sizes of the raw AML resource descriptors, indexed by resource type. - * Zero indicates a reserved (and therefore invalid) resource type. - */ -const u8 acpi_gbl_resource_aml_sizes[] = { - /* Small descriptors */ - - 0, - 0, - 0, - 0, - ACPI_AML_SIZE_SMALL(struct aml_resource_irq), - ACPI_AML_SIZE_SMALL(struct aml_resource_dma), - ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent), - ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent), - ACPI_AML_SIZE_SMALL(struct aml_resource_io), - ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io), - 0, - 0, - 0, - 0, - ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small), - ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag), - - /* Large descriptors */ - - 0, - ACPI_AML_SIZE_LARGE(struct aml_resource_memory24), - ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register), - 0, - ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large), - ACPI_AML_SIZE_LARGE(struct aml_resource_memory32), - ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32), - ACPI_AML_SIZE_LARGE(struct aml_resource_address32), - ACPI_AML_SIZE_LARGE(struct aml_resource_address16), - ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq), - ACPI_AML_SIZE_LARGE(struct aml_resource_address64), - ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64) -}; - -/* - * Resource types, used to validate the resource length field. - * The length of fixed-length types must match exactly, variable - * lengths must meet the minimum required length, etc. - * Zero indicates a reserved (and therefore invalid) resource type. - */ -static const u8 acpi_gbl_resource_types[] = { - /* Small descriptors */ - - 0, - 0, - 0, - 0, - ACPI_SMALL_VARIABLE_LENGTH, - ACPI_FIXED_LENGTH, - ACPI_SMALL_VARIABLE_LENGTH, - ACPI_FIXED_LENGTH, - ACPI_FIXED_LENGTH, - ACPI_FIXED_LENGTH, - 0, - 0, - 0, - 0, - ACPI_VARIABLE_LENGTH, - ACPI_FIXED_LENGTH, - - /* Large descriptors */ - - 0, - ACPI_FIXED_LENGTH, - ACPI_FIXED_LENGTH, - 0, - ACPI_VARIABLE_LENGTH, - ACPI_FIXED_LENGTH, - ACPI_FIXED_LENGTH, - ACPI_VARIABLE_LENGTH, - ACPI_VARIABLE_LENGTH, - ACPI_VARIABLE_LENGTH, - ACPI_VARIABLE_LENGTH, - ACPI_FIXED_LENGTH -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ut_walk_aml_resources - * - * PARAMETERS: Aml - Pointer to the raw AML resource template - * aml_length - Length of the entire template - * user_function - Called once for each descriptor found. If - * NULL, a pointer to the end_tag is returned - * Context - Passed to user_function - * - * RETURN: Status - * - * DESCRIPTION: Walk a raw AML resource list(buffer). User function called - * once for each resource found. - * - ******************************************************************************/ - -acpi_status -acpi_ut_walk_aml_resources(u8 * aml, - acpi_size aml_length, - acpi_walk_aml_callback user_function, void **context) -{ - acpi_status status; - u8 *end_aml; - u8 resource_index; - u32 length; - u32 offset = 0; - - ACPI_FUNCTION_TRACE(ut_walk_aml_resources); - - /* The absolute minimum resource template is one end_tag descriptor */ - - if (aml_length < sizeof(struct aml_resource_end_tag)) { - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); - } - - /* Point to the end of the resource template buffer */ - - end_aml = aml + aml_length; - - /* Walk the byte list, abort on any invalid descriptor type or length */ - - while (aml < end_aml) { - - /* Validate the Resource Type and Resource Length */ - - status = acpi_ut_validate_resource(aml, &resource_index); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get the length of this descriptor */ - - length = acpi_ut_get_descriptor_length(aml); - - /* Invoke the user function */ - - if (user_function) { - status = - user_function(aml, length, offset, resource_index, - context); - if (ACPI_FAILURE(status)) { - return (status); - } - } - - /* An end_tag descriptor terminates this resource template */ - - if (acpi_ut_get_resource_type(aml) == - ACPI_RESOURCE_NAME_END_TAG) { - /* - * There must be at least one more byte in the buffer for - * the 2nd byte of the end_tag - */ - if ((aml + 1) >= end_aml) { - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); - } - - /* Return the pointer to the end_tag if requested */ - - if (!user_function) { - *context = aml; - } - - /* Normal exit */ - - return_ACPI_STATUS(AE_OK); - } - - aml += length; - offset += length; - } - - /* Did not find an end_tag descriptor */ - - return (AE_AML_NO_RESOURCE_END_TAG); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_validate_resource - * - * PARAMETERS: Aml - Pointer to the raw AML resource descriptor - * return_index - Where the resource index is returned. NULL - * if the index is not required. - * - * RETURN: Status, and optionally the Index into the global resource tables - * - * DESCRIPTION: Validate an AML resource descriptor by checking the Resource - * Type and Resource Length. Returns an index into the global - * resource information/dispatch tables for later use. - * - ******************************************************************************/ - -acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) -{ - u8 resource_type; - u8 resource_index; - acpi_rs_length resource_length; - acpi_rs_length minimum_resource_length; - - ACPI_FUNCTION_ENTRY(); - - /* - * 1) Validate the resource_type field (Byte 0) - */ - resource_type = ACPI_GET8(aml); - - /* - * Byte 0 contains the descriptor name (Resource Type) - * Examine the large/small bit in the resource header - */ - if (resource_type & ACPI_RESOURCE_NAME_LARGE) { - - /* Verify the large resource type (name) against the max */ - - if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) { - return (AE_AML_INVALID_RESOURCE_TYPE); - } - - /* - * Large Resource Type -- bits 6:0 contain the name - * Translate range 0x80-0x8B to index range 0x10-0x1B - */ - resource_index = (u8) (resource_type - 0x70); - } else { - /* - * Small Resource Type -- bits 6:3 contain the name - * Shift range to index range 0x00-0x0F - */ - resource_index = (u8) - ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); - } - - /* Check validity of the resource type, zero indicates name is invalid */ - - if (!acpi_gbl_resource_types[resource_index]) { - return (AE_AML_INVALID_RESOURCE_TYPE); - } - - /* - * 2) Validate the resource_length field. This ensures that the length - * is at least reasonable, and guarantees that it is non-zero. - */ - resource_length = acpi_ut_get_resource_length(aml); - minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index]; - - /* Validate based upon the type of resource - fixed length or variable */ - - switch (acpi_gbl_resource_types[resource_index]) { - case ACPI_FIXED_LENGTH: - - /* Fixed length resource, length must match exactly */ - - if (resource_length != minimum_resource_length) { - return (AE_AML_BAD_RESOURCE_LENGTH); - } - break; - - case ACPI_VARIABLE_LENGTH: - - /* Variable length resource, length must be at least the minimum */ - - if (resource_length < minimum_resource_length) { - return (AE_AML_BAD_RESOURCE_LENGTH); - } - break; - - case ACPI_SMALL_VARIABLE_LENGTH: - - /* Small variable length resource, length can be (Min) or (Min-1) */ - - if ((resource_length > minimum_resource_length) || - (resource_length < (minimum_resource_length - 1))) { - return (AE_AML_BAD_RESOURCE_LENGTH); - } - break; - - default: - - /* Shouldn't happen (because of validation earlier), but be sure */ - - return (AE_AML_INVALID_RESOURCE_TYPE); - } - - /* Optionally return the resource table index */ - - if (return_index) { - *return_index = resource_index; - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_resource_type - * - * PARAMETERS: Aml - Pointer to the raw AML resource descriptor - * - * RETURN: The Resource Type with no extraneous bits (except the - * Large/Small descriptor bit -- this is left alone) - * - * DESCRIPTION: Extract the Resource Type/Name from the first byte of - * a resource descriptor. - * - ******************************************************************************/ - -u8 acpi_ut_get_resource_type(void *aml) -{ - ACPI_FUNCTION_ENTRY(); - - /* - * Byte 0 contains the descriptor name (Resource Type) - * Examine the large/small bit in the resource header - */ - if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { - - /* Large Resource Type -- bits 6:0 contain the name */ - - return (ACPI_GET8(aml)); - } else { - /* Small Resource Type -- bits 6:3 contain the name */ - - return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK)); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_resource_length - * - * PARAMETERS: Aml - Pointer to the raw AML resource descriptor - * - * RETURN: Byte Length - * - * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By - * definition, this does not include the size of the descriptor - * header or the length field itself. - * - ******************************************************************************/ - -u16 acpi_ut_get_resource_length(void *aml) -{ - acpi_rs_length resource_length; - - ACPI_FUNCTION_ENTRY(); - - /* - * Byte 0 contains the descriptor name (Resource Type) - * Examine the large/small bit in the resource header - */ - if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { - - /* Large Resource type -- bytes 1-2 contain the 16-bit length */ - - ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1)); - - } else { - /* Small Resource type -- bits 2:0 of byte 0 contain the length */ - - resource_length = (u16) (ACPI_GET8(aml) & - ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); - } - - return (resource_length); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_resource_header_length - * - * PARAMETERS: Aml - Pointer to the raw AML resource descriptor - * - * RETURN: Length of the AML header (depends on large/small descriptor) - * - * DESCRIPTION: Get the length of the header for this resource. - * - ******************************************************************************/ - -u8 acpi_ut_get_resource_header_length(void *aml) -{ - ACPI_FUNCTION_ENTRY(); - - /* Examine the large/small bit in the resource header */ - - if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { - return (sizeof(struct aml_resource_large_header)); - } else { - return (sizeof(struct aml_resource_small_header)); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_descriptor_length - * - * PARAMETERS: Aml - Pointer to the raw AML resource descriptor - * - * RETURN: Byte length - * - * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the - * length of the descriptor header and the length field itself. - * Used to walk descriptor lists. - * - ******************************************************************************/ - -u32 acpi_ut_get_descriptor_length(void *aml) -{ - ACPI_FUNCTION_ENTRY(); - - /* - * Get the Resource Length (does not include header length) and add - * the header length (depends on if this is a small or large resource) - */ - return (acpi_ut_get_resource_length(aml) + - acpi_ut_get_resource_header_length(aml)); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_get_resource_end_tag - * - * PARAMETERS: obj_desc - The resource template buffer object - * end_tag - Where the pointer to the end_tag is returned - * - * RETURN: Status, pointer to the end tag - * - * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template - * Note: allows a buffer length of zero. - * - ******************************************************************************/ - -acpi_status -acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, - u8 ** end_tag) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_get_resource_end_tag); - - /* Allow a buffer length of zero */ - - if (!obj_desc->buffer.length) { - *end_tag = obj_desc->buffer.pointer; - return_ACPI_STATUS(AE_OK); - } - - /* Validate the template and get a pointer to the end_tag */ - - status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer, - obj_desc->buffer.length, NULL, - (void **)end_tag); - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c deleted file mode 100644 index 54c3461e2f26..000000000000 --- a/drivers/acpi/utilities/utstate.c +++ /dev/null @@ -1,347 +0,0 @@ -/******************************************************************************* - * - * Module Name: utstate - state object support procedures - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utstate") - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_pkg_state_and_push - * - * PARAMETERS: Object - Object to be added to the new state - * Action - Increment/Decrement - * state_list - List the state will be added to - * - * RETURN: Status - * - * DESCRIPTION: Create a new state and push it - * - ******************************************************************************/ -acpi_status -acpi_ut_create_pkg_state_and_push(void *internal_object, - void *external_object, - u16 index, - union acpi_generic_state **state_list) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_ENTRY(); - - state = - acpi_ut_create_pkg_state(internal_object, external_object, index); - if (!state) { - return (AE_NO_MEMORY); - } - - acpi_ut_push_generic_state(state_list, state); - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_push_generic_state - * - * PARAMETERS: list_head - Head of the state stack - * State - State object to push - * - * RETURN: None - * - * DESCRIPTION: Push a state object onto a state stack - * - ******************************************************************************/ - -void -acpi_ut_push_generic_state(union acpi_generic_state **list_head, - union acpi_generic_state *state) -{ - ACPI_FUNCTION_TRACE(ut_push_generic_state); - - /* Push the state object onto the front of the list (stack) */ - - state->common.next = *list_head; - *list_head = state; - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_pop_generic_state - * - * PARAMETERS: list_head - Head of the state stack - * - * RETURN: The popped state object - * - * DESCRIPTION: Pop a state object from a state stack - * - ******************************************************************************/ - -union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state - **list_head) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_TRACE(ut_pop_generic_state); - - /* Remove the state object at the head of the list (stack) */ - - state = *list_head; - if (state) { - - /* Update the list head */ - - *list_head = state->common.next; - } - - return_PTR(state); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_generic_state - * - * PARAMETERS: None - * - * RETURN: The new state object. NULL on failure. - * - * DESCRIPTION: Create a generic state object. Attempt to obtain one from - * the global state cache; If none available, create a new one. - * - ******************************************************************************/ - -union acpi_generic_state *acpi_ut_create_generic_state(void) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_ENTRY(); - - state = acpi_os_acquire_object(acpi_gbl_state_cache); - if (state) { - - /* Initialize */ - memset(state, 0, sizeof(union acpi_generic_state)); - state->common.descriptor_type = ACPI_DESC_TYPE_STATE; - } - - return (state); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_thread_state - * - * PARAMETERS: None - * - * RETURN: New Thread State. NULL on failure - * - * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used - * to track per-thread info during method execution - * - ******************************************************************************/ - -struct acpi_thread_state *acpi_ut_create_thread_state(void) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_TRACE(ut_create_thread_state); - - /* Create the generic state object */ - - state = acpi_ut_create_generic_state(); - if (!state) { - return_PTR(NULL); - } - - /* Init fields specific to the update struct */ - - state->common.descriptor_type = ACPI_DESC_TYPE_STATE_THREAD; - state->thread.thread_id = acpi_os_get_thread_id(); - - /* Check for invalid thread ID - zero is very bad, it will break things */ - - if (!state->thread.thread_id) { - ACPI_ERROR((AE_INFO, "Invalid zero ID from AcpiOsGetThreadId")); - state->thread.thread_id = (acpi_thread_id) 1; - } - - return_PTR((struct acpi_thread_state *)state); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_update_state - * - * PARAMETERS: Object - Initial Object to be installed in the state - * Action - Update action to be performed - * - * RETURN: New state object, null on failure - * - * DESCRIPTION: Create an "Update State" - a flavor of the generic state used - * to update reference counts and delete complex objects such - * as packages. - * - ******************************************************************************/ - -union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object - *object, u16 action) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_TRACE_PTR(ut_create_update_state, object); - - /* Create the generic state object */ - - state = acpi_ut_create_generic_state(); - if (!state) { - return_PTR(NULL); - } - - /* Init fields specific to the update struct */ - - state->common.descriptor_type = ACPI_DESC_TYPE_STATE_UPDATE; - state->update.object = object; - state->update.value = action; - - return_PTR(state); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_pkg_state - * - * PARAMETERS: Object - Initial Object to be installed in the state - * Action - Update action to be performed - * - * RETURN: New state object, null on failure - * - * DESCRIPTION: Create a "Package State" - * - ******************************************************************************/ - -union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, - void *external_object, - u16 index) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_TRACE_PTR(ut_create_pkg_state, internal_object); - - /* Create the generic state object */ - - state = acpi_ut_create_generic_state(); - if (!state) { - return_PTR(NULL); - } - - /* Init fields specific to the update struct */ - - state->common.descriptor_type = ACPI_DESC_TYPE_STATE_PACKAGE; - state->pkg.source_object = (union acpi_operand_object *)internal_object; - state->pkg.dest_object = external_object; - state->pkg.index = index; - state->pkg.num_packages = 1; - - return_PTR(state); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_control_state - * - * PARAMETERS: None - * - * RETURN: New state object, null on failure - * - * DESCRIPTION: Create a "Control State" - a flavor of the generic state used - * to support nested IF/WHILE constructs in the AML. - * - ******************************************************************************/ - -union acpi_generic_state *acpi_ut_create_control_state(void) -{ - union acpi_generic_state *state; - - ACPI_FUNCTION_TRACE(ut_create_control_state); - - /* Create the generic state object */ - - state = acpi_ut_create_generic_state(); - if (!state) { - return_PTR(NULL); - } - - /* Init fields specific to the control struct */ - - state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL; - state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING; - - return_PTR(state); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_delete_generic_state - * - * PARAMETERS: State - The state object to be deleted - * - * RETURN: None - * - * DESCRIPTION: Release a state object to the state cache. NULL state objects - * are ignored. - * - ******************************************************************************/ - -void acpi_ut_delete_generic_state(union acpi_generic_state *state) -{ - ACPI_FUNCTION_TRACE(ut_delete_generic_state); - - /* Ignore null state */ - - if (state) { - (void)acpi_os_release_object(acpi_gbl_state_cache, state); - } - return_VOID; -} diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c deleted file mode 100644 index 5b27724a2749..000000000000 --- a/drivers/acpi/utilities/utxface.c +++ /dev/null @@ -1,512 +0,0 @@ -/****************************************************************************** - * - * Module Name: utxface - External interfaces for "global" ACPI functions - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2008, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utxface") - -#ifndef ACPI_ASL_COMPILER -/******************************************************************************* - * - * FUNCTION: acpi_initialize_subsystem - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Initializes all global variables. This is the first function - * called, so any early initialization belongs here. - * - ******************************************************************************/ -acpi_status __init acpi_initialize_subsystem(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_initialize_subsystem); - - acpi_gbl_startup_flags = ACPI_SUBSYSTEM_INITIALIZE; - ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace()); - - /* Initialize the OS-Dependent layer */ - - status = acpi_os_initialize(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization")); - return_ACPI_STATUS(status); - } - - /* Initialize all globals used by the subsystem */ - - status = acpi_ut_init_globals(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "During initialization of globals")); - return_ACPI_STATUS(status); - } - - /* Create the default mutex objects */ - - status = acpi_ut_mutex_initialize(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "During Global Mutex creation")); - return_ACPI_STATUS(status); - } - - /* - * Initialize the namespace manager and - * the root of the namespace tree - */ - status = acpi_ns_root_initialize(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "During Namespace initialization")); - return_ACPI_STATUS(status); - } - - /* If configured, initialize the AML debugger */ - - ACPI_DEBUGGER_EXEC(status = acpi_db_initialize()); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_enable_subsystem - * - * PARAMETERS: Flags - Init/enable Options - * - * RETURN: Status - * - * DESCRIPTION: Completes the subsystem initialization including hardware. - * Puts system into ACPI mode if it isn't already. - * - ******************************************************************************/ -acpi_status acpi_enable_subsystem(u32 flags) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(acpi_enable_subsystem); - - /* Enable ACPI mode */ - - if (!(flags & ACPI_NO_ACPI_ENABLE)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Going into ACPI mode\n")); - - acpi_gbl_original_mode = acpi_hw_get_mode(); - - status = acpi_enable(); - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, "AcpiEnable failed")); - return_ACPI_STATUS(status); - } - } - - /* - * Obtain a permanent mapping for the FACS. This is required for the - * Global Lock and the Firmware Waking Vector - */ - status = acpi_tb_initialize_facs(); - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, "Could not map the FACS table")); - return_ACPI_STATUS(status); - } - - /* - * Install the default op_region handlers. These are installed unless - * other handlers have already been installed via the - * install_address_space_handler interface. - */ - if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Installing default address space handlers\n")); - - status = acpi_ev_install_region_handlers(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Initialize ACPI Event handling (Fixed and General Purpose) - * - * Note1: We must have the hardware and events initialized before we can - * execute any control methods safely. Any control method can require - * ACPI hardware support, so the hardware must be fully initialized before - * any method execution! - * - * Note2: Fixed events are initialized and enabled here. GPEs are - * initialized, but cannot be enabled until after the hardware is - * completely initialized (SCI and global_lock activated) - */ - if (!(flags & ACPI_NO_EVENT_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Initializing ACPI events\n")); - - status = acpi_ev_initialize_events(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Install the SCI handler and Global Lock handler. This completes the - * hardware initialization. - */ - if (!(flags & ACPI_NO_HANDLER_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Installing SCI/GL handlers\n")); - - status = acpi_ev_install_xrupt_handlers(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_enable_subsystem) - -/******************************************************************************* - * - * FUNCTION: acpi_initialize_objects - * - * PARAMETERS: Flags - Init/enable Options - * - * RETURN: Status - * - * DESCRIPTION: Completes namespace initialization by initializing device - * objects and executing AML code for Regions, buffers, etc. - * - ******************************************************************************/ -acpi_status acpi_initialize_objects(u32 flags) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(acpi_initialize_objects); - - /* - * Run all _REG methods - * - * Note: Any objects accessed by the _REG methods will be automatically - * initialized, even if they contain executable AML (see the call to - * acpi_ns_initialize_objects below). - */ - if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Executing _REG OpRegion methods\n")); - - status = acpi_ev_initialize_op_regions(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Initialize the objects that remain uninitialized. This runs the - * executable AML that may be part of the declaration of these objects: - * operation_regions, buffer_fields, Buffers, and Packages. - */ - if (!(flags & ACPI_NO_OBJECT_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Completing Initialization of ACPI Objects\n")); - - status = acpi_ns_initialize_objects(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Initialize all device objects in the namespace. This runs the device - * _STA and _INI methods. - */ - if (!(flags & ACPI_NO_DEVICE_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Initializing ACPI Devices\n")); - - status = acpi_ns_initialize_devices(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Complete the GPE initialization for the GPE blocks defined in the FADT - * (GPE block 0 and 1). - * - * Note1: This is where the _PRW methods are executed for the GPEs. These - * methods can only be executed after the SCI and Global Lock handlers are - * installed and initialized. - * - * Note2: Currently, there seems to be no need to run the _REG methods - * before execution of the _PRW methods and enabling of the GPEs. - */ - if (!(flags & ACPI_NO_EVENT_INIT)) { - status = acpi_ev_install_fadt_gpes(); - if (ACPI_FAILURE(status)) - return (status); - } - - /* - * Empty the caches (delete the cached objects) on the assumption that - * the table load filled them up more than they will be at runtime -- - * thus wasting non-paged memory. - */ - status = acpi_purge_cached_objects(); - - acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK; - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_initialize_objects) - -#endif -/******************************************************************************* - * - * FUNCTION: acpi_terminate - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Shutdown the ACPI subsystem. Release all resources. - * - ******************************************************************************/ -acpi_status acpi_terminate(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_terminate); - - /* Terminate the AML Debugger if present */ - - ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE); - - /* Shutdown and free all resources */ - - acpi_ut_subsystem_shutdown(); - - /* Free the mutex objects */ - - acpi_ut_mutex_terminate(); - -#ifdef ACPI_DEBUGGER - - /* Shut down the debugger */ - - acpi_db_terminate(); -#endif - - /* Now we can shutdown the OS-dependent layer */ - - status = acpi_os_terminate(); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_terminate) -#ifndef ACPI_ASL_COMPILER -#ifdef ACPI_FUTURE_USAGE -/******************************************************************************* - * - * FUNCTION: acpi_subsystem_status - * - * PARAMETERS: None - * - * RETURN: Status of the ACPI subsystem - * - * DESCRIPTION: Other drivers that use the ACPI subsystem should call this - * before making any other calls, to ensure the subsystem - * initialized successfully. - * - ******************************************************************************/ -acpi_status acpi_subsystem_status(void) -{ - - if (acpi_gbl_startup_flags & ACPI_INITIALIZED_OK) { - return (AE_OK); - } else { - return (AE_ERROR); - } -} - -ACPI_EXPORT_SYMBOL(acpi_subsystem_status) - -/******************************************************************************* - * - * FUNCTION: acpi_get_system_info - * - * PARAMETERS: out_buffer - A buffer to receive the resources for the - * device - * - * RETURN: Status - the status of the call - * - * DESCRIPTION: This function is called to get information about the current - * state of the ACPI subsystem. It will return system information - * in the out_buffer. - * - * If the function fails an appropriate status will be returned - * and the value of out_buffer is undefined. - * - ******************************************************************************/ -acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) -{ - struct acpi_system_info *info_ptr; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_get_system_info); - - /* Parameter validation */ - - status = acpi_ut_validate_buffer(out_buffer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Validate/Allocate/Clear caller buffer */ - - status = - acpi_ut_initialize_buffer(out_buffer, - sizeof(struct acpi_system_info)); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Populate the return buffer - */ - info_ptr = (struct acpi_system_info *)out_buffer->pointer; - - info_ptr->acpi_ca_version = ACPI_CA_VERSION; - - /* System flags (ACPI capabilities) */ - - info_ptr->flags = ACPI_SYS_MODE_ACPI; - - /* Timer resolution - 24 or 32 bits */ - - if (acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) { - info_ptr->timer_resolution = 24; - } else { - info_ptr->timer_resolution = 32; - } - - /* Clear the reserved fields */ - - info_ptr->reserved1 = 0; - info_ptr->reserved2 = 0; - - /* Current debug levels */ - - info_ptr->debug_layer = acpi_dbg_layer; - info_ptr->debug_level = acpi_dbg_level; - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_get_system_info) - -/***************************************************************************** - * - * FUNCTION: acpi_install_initialization_handler - * - * PARAMETERS: Handler - Callback procedure - * Function - Not (currently) used, see below - * - * RETURN: Status - * - * DESCRIPTION: Install an initialization handler - * - * TBD: When a second function is added, must save the Function also. - * - ****************************************************************************/ -acpi_status -acpi_install_initialization_handler(acpi_init_handler handler, u32 function) -{ - - if (!handler) { - return (AE_BAD_PARAMETER); - } - - if (acpi_gbl_init_handler) { - return (AE_ALREADY_EXISTS); - } - - acpi_gbl_init_handler = handler; - return AE_OK; -} - -ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) -#endif /* ACPI_FUTURE_USAGE */ -/***************************************************************************** - * - * FUNCTION: acpi_purge_cached_objects - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Empty all caches (delete the cached objects) - * - ****************************************************************************/ -acpi_status acpi_purge_cached_objects(void) -{ - ACPI_FUNCTION_TRACE(acpi_purge_cached_objects); - - (void)acpi_os_purge_cache(acpi_gbl_state_cache); - (void)acpi_os_purge_cache(acpi_gbl_operand_cache); - (void)acpi_os_purge_cache(acpi_gbl_ps_node_cache); - (void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache); - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) -#endif diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c new file mode 100644 index 000000000000..2d34806d45dd --- /dev/null +++ b/drivers/acpi/wakeup.c @@ -0,0 +1,167 @@ +/* + * wakeup.c - support wakeup devices + * Copyright (C) 2004 Li Shaohua + */ + +#include +#include +#include +#include +#include +#include "sleep.h" + +#define _COMPONENT ACPI_SYSTEM_COMPONENT +ACPI_MODULE_NAME("wakeup_devices") + +extern struct list_head acpi_wakeup_device_list; +extern spinlock_t acpi_device_lock; + +/** + * acpi_enable_wakeup_device_prep - prepare wakeup devices + * @sleep_state: ACPI state + * Enable all wakup devices power if the devices' wakeup level + * is higher than requested sleep level + */ + +void acpi_enable_wakeup_device_prep(u8 sleep_state) +{ + struct list_head *node, *next; + + spin_lock(&acpi_device_lock); + list_for_each_safe(node, next, &acpi_wakeup_device_list) { + struct acpi_device *dev = container_of(node, + struct acpi_device, + wakeup_list); + + if (!dev->wakeup.flags.valid || + !dev->wakeup.state.enabled || + (sleep_state > (u32) dev->wakeup.sleep_state)) + continue; + + spin_unlock(&acpi_device_lock); + acpi_enable_wakeup_device_power(dev, sleep_state); + spin_lock(&acpi_device_lock); + } + spin_unlock(&acpi_device_lock); +} + +/** + * acpi_enable_wakeup_device - enable wakeup devices + * @sleep_state: ACPI state + * Enable all wakup devices's GPE + */ +void acpi_enable_wakeup_device(u8 sleep_state) +{ + struct list_head *node, *next; + + /* + * Caution: this routine must be invoked when interrupt is disabled + * Refer ACPI2.0: P212 + */ + spin_lock(&acpi_device_lock); + list_for_each_safe(node, next, &acpi_wakeup_device_list) { + struct acpi_device *dev = + container_of(node, struct acpi_device, wakeup_list); + + if (!dev->wakeup.flags.valid) + continue; + + /* If users want to disable run-wake GPE, + * we only disable it for wake and leave it for runtime + */ + if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared) + || sleep_state > (u32) dev->wakeup.sleep_state) { + if (dev->wakeup.flags.run_wake) { + spin_unlock(&acpi_device_lock); + /* set_gpe_type will disable GPE, leave it like that */ + acpi_set_gpe_type(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, + ACPI_GPE_TYPE_RUNTIME); + spin_lock(&acpi_device_lock); + } + continue; + } + spin_unlock(&acpi_device_lock); + if (!dev->wakeup.flags.run_wake) + acpi_enable_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number); + spin_lock(&acpi_device_lock); + } + spin_unlock(&acpi_device_lock); +} + +/** + * acpi_disable_wakeup_device - disable devices' wakeup capability + * @sleep_state: ACPI state + * Disable all wakup devices's GPE and wakeup capability + */ +void acpi_disable_wakeup_device(u8 sleep_state) +{ + struct list_head *node, *next; + + spin_lock(&acpi_device_lock); + list_for_each_safe(node, next, &acpi_wakeup_device_list) { + struct acpi_device *dev = + container_of(node, struct acpi_device, wakeup_list); + + if (!dev->wakeup.flags.valid) + continue; + + if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared) + || sleep_state > (u32) dev->wakeup.sleep_state) { + if (dev->wakeup.flags.run_wake) { + spin_unlock(&acpi_device_lock); + acpi_set_gpe_type(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, + ACPI_GPE_TYPE_WAKE_RUN); + /* Re-enable it, since set_gpe_type will disable it */ + acpi_enable_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number); + spin_lock(&acpi_device_lock); + } + continue; + } + + spin_unlock(&acpi_device_lock); + acpi_disable_wakeup_device_power(dev); + /* Never disable run-wake GPE */ + if (!dev->wakeup.flags.run_wake) { + acpi_disable_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number); + acpi_clear_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, ACPI_NOT_ISR); + } + spin_lock(&acpi_device_lock); + } + spin_unlock(&acpi_device_lock); +} + +static int __init acpi_wakeup_device_init(void) +{ + struct list_head *node, *next; + + if (acpi_disabled) + return 0; + + spin_lock(&acpi_device_lock); + list_for_each_safe(node, next, &acpi_wakeup_device_list) { + struct acpi_device *dev = container_of(node, + struct acpi_device, + wakeup_list); + /* In case user doesn't load button driver */ + if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled) + continue; + spin_unlock(&acpi_device_lock); + acpi_set_gpe_type(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, + ACPI_GPE_TYPE_WAKE_RUN); + acpi_enable_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number); + dev->wakeup.state.enabled = 1; + spin_lock(&acpi_device_lock); + } + spin_unlock(&acpi_device_lock); + return 0; +} + +late_initcall(acpi_wakeup_device_init); -- cgit v1.2.3-59-g8ed1b